import { Err, Result } from "../result"; import { RuntimeType, runtimeTypeOf } from "../issues/shared"; import { OpaqueType } from "../type"; export type GuardIssue = { readonly kind: "guard"; readonly name: string; readonly threw: boolean; readonly subject: RuntimeType; }; type Guard = (val: any) => val is T export class Is extends OpaqueType { readonly name: string readonly isT: Guard constructor(name: string, guard: Guard) { super() this.name = name this.isT = guard } check(val: any): Result { try { if(this.isT(val)) return val; } catch { return new Err({ kind: "guard", name: this.name, threw: true, subject: runtimeTypeOf(val), }); } return new Err({ kind: "guard", name: this.name, threw: false, subject: runtimeTypeOf(val), }); } } export function is(name: string, guard: Guard) { return new Is(name, guard) }