Skip to content

Instantly share code, notes, and snippets.

@bqqbarbhg
Created July 24, 2023 18:06
Show Gist options
  • Select an option

  • Save bqqbarbhg/cf6a079356bd8ac3db4f924ef38f03a7 to your computer and use it in GitHub Desktop.

Select an option

Save bqqbarbhg/cf6a079356bd8ac3db4f924ef38f03a7 to your computer and use it in GitHub Desktop.
export const fail = Symbol("fail")
export type Fail = typeof fail
export function string(v: any): string | Fail {
return typeof v === "string" ? v : fail
}
export function number(v: any): number | Fail {
return typeof v === "number" ? v : fail
return v
}
export function boolean(v: any): boolean | Fail {
return typeof v === "boolean" ? v : fail
}
type Validator = (a: any) => any | Fail
type ValidatorResult<T extends Validator> = Exclude<ReturnType<T>, Fail>
type ObjectValidator = {
[key: string]: Validator
}
type ObjectResult<T extends ObjectValidator> = {
[key in keyof T]: ValidatorResult<T[key]>
} | Fail
type UnionValidator = {
[key: number]: Validator
}
type UnionResult<T extends UnionValidator> = {
[key in keyof T]: ValidatorResult<T[key]>
}[number] | Fail
export function object<T extends ObjectValidator>(spec: T): ((obj: any) => ObjectResult<T>) {
return (obj: any) => {
const result: any = { }
for (const key of Object.keys(spec)) {
const r = (spec as any)[key]!(obj[key])
if (r === fail) return fail
result[key] = r
}
return result as ObjectResult<T>
}
}
export function array<T extends Validator>(spec: T): ((obj: any) => ValidatorResult<T>[] | Fail) {
return (obj: any) => {
const result = []
for (const value of obj) {
const r = spec(value)
if (r === fail) return fail
result.push(r)
}
return result
}
}
export function maybe<T extends Validator>(spec: T): ((obj: any) => ValidatorResult<T> | undefined | Fail) {
return (obj: any) => {
if (obj === undefined) return undefined
return spec(obj)
}
}
export function literal<T extends string | number | boolean>(spec: T): ((obj: any) => T | Fail) {
return (obj: any) => {
if (obj !== spec) return fail
return spec
}
}
export function union<T extends UnionValidator>(spec: T): ((obj: any) => UnionResult<T>) {
return (obj: any) => {
for (const s of (spec as unknown as Validator[])) {
const r = s(obj)
if (r !== fail) return r
}
return fail
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment