import { Err, Result } from "../result"; import { at } from "../issue"; import { typeMismatch } from "../issues/shared"; import { asKind } from "../as-kind"; import { TypedKind } from "../kind"; import { Projection, Type, TypeImpl } from "../type"; export class SetType extends TypeImpl> { readonly valueType: TypedKind; constructor(v: Type) { super(); this.valueType = asKind(v); } check(val: any): Result> { if(!(val instanceof Set)) return new Err(typeMismatch("set", val)); let index = 0; for(const value of val) { const result = this.valueType.check(value); if(result instanceof Err) { return new Err(at({ kind: "set-value", index }, result.issue, "set")); } index += 1; } return val as Set; } /* * Slice each captured value in one pass so nested child sliceResult overrides are preserved. */ sliceResult(val: any): Result> { if(!(val instanceof Set)) return new Err(typeMismatch("set", val)); const result = new Set(); let index = 0; for(const value of val) { const sliced = this.valueType.sliceResult(value); if(sliced instanceof Err) { return new Err(at({ kind: "set-value", index }, sliced.issue, "set")); } result.add(sliced); index += 1; } return result; } protected merge(type: TypedKind): TypedKind & R> | undefined { if(!(type instanceof SetType)) return undefined; return asKind & R>(new SetType( this.valueType.and(type.valueType), )); } protected project(val: any): Projection> { const result = new Set(); for(const value of val) { const projection = this.projectionOf(this.valueType, value); result.add(projection.kind === "none" ? value : projection.value); } return { kind: "structural", value: result }; } } export function set(v: Type): SetType { return new SetType(v); }