// Copied from Zod // TODO: review all the types export type Primitive = | string // | number | symbol | bigint | boolean | null | undefined export type Dictionary = { [key: string]: unknown } export type MetaNever = { meta?: never } // TODO: change to undefined ? or remove? export type MetaObj = { meta: TMeta } /** @typeparam TBad - Each struct can returns some kinds of issues (not throwing) @typeparam TGood - The type which is guaranteed to be the output of the validator @typeparam TInput - The type of the input value. @example a numeric string can be based on the definition of a string. so you can base a numeric string on a string struct (if you want). By default the `unknown` struct is used. That is the only core struct */ export type Sure< // TBad = unknown, TGood = unknown, TInput = unknown, // TMeta extends MetaNever | MetaObj = MetaNever | MetaObj, > = ((value: TInput) => Good | Bad) & TMeta /** Returns the exact function back. But the types are inferred automatically for you. Expects you to pass a function that gets an `unknown` value and returns either: [true, ] [false, ] Check the `sure.ts` version to check the types @example Check playground.ts to hover over variables */ export function sure( insure: Sure, meta: TMeta ): Sure> { return Object.assign(insure, { meta }) } export function pure( insure: Sure ): Sure { return insure } // So that `as const` is not needed for literals export function bad(val: TBad): Bad export function bad(val: TBad): Bad export function bad(val: TBad): Bad { return [false, val] } // export function good(val: TGood): Good export function good(val: TGood): Good export function good(val: TGood): Good { return [true, val] } export type Unsure = // Good | Bad export type Good = readonly [true, T] export type Bad = readonly [false, T] export type InferBad< // Add the Sure constraint T extends Sure< unknown, unknown, // Input issue any, MetaObj | MetaNever >, > = // T extends (...args: any) => infer COutput // ? COutput extends readonly [false, infer CGood] // ? CGood : never : never export type InferGood< // Add the Sure constraint T extends Sure< unknown, unknown, // Input issue any, MetaObj | MetaNever >, > = // T extends (...args: any) => infer COutput // ? COutput extends readonly [true, infer CGood] // ? CGood : never : never export type InferInput< T extends Sure< unknown, unknown, // Input issue any, MetaObj | MetaNever >, > = // T extends Sure< unknown, unknown, // Input issue infer CFrom, MetaObj | MetaNever > ? // // CFrom : never export type InferMeta> = // T extends Sure // ? CMeta : {}