/** * This library reifies typescript types so that we can validate them at runtime. * * The idea was heavily inspired by https://gcanti.github.io/io-ts/ */ type TOpts = { logFailures: boolean; }; export type Schema = (value: unknown, opts?: TOpts) => value is TInner; type ExtractTypeguard = T extends (v: unknown, o?: TOpts) => v is infer U ? U : never; export type TypeOf> = ExtractTypeguard; type OptionalSchemaKeys = { [Index in keyof TSchemaMap]: Schema extends TSchemaMap[Index] ? Index : never; }[keyof TSchemaMap]; type NonOptionalSchemaKeys = { [Index in keyof TSchemaMap]: Schema extends TSchemaMap[Index] ? never : Index; }[keyof TSchemaMap]; export type UnwrapSchemaMap = keyof TSchemaMap extends never ? Record : { [SchemaMapIndex in OptionalSchemaKeys]?: TSchemaMap[SchemaMapIndex] extends Schema ? TypeOf : never; } & { [SchemaMapIndex in NonOptionalSchemaKeys]: TSchemaMap[SchemaMapIndex] extends Schema ? TypeOf : never; }; export declare const undefinedtype: (value: unknown) => value is undefined; type Extends = [A] extends [B] ? true : false; type NonGenericExceptBooleans = true extends Extends | Extends ? never : A; type NonGeneric = true extends Extends ? never : NonGenericExceptBooleans; export declare function literal(inner: NonGeneric): (value: unknown) => value is NonGeneric; export declare const number: (value: unknown) => value is number; export declare const string: (value: unknown) => value is string; export declare const boolean: (value: unknown) => value is boolean; export declare const nulltype: (value: unknown) => value is null; /** * Note: I'm explicitly excluding dictionaries from this library. * I have seen very few legitimate uses of dictionaries in API design * and more common than not, the use case is better served by a shape * or an array. */ /** * If we define the below schema and extracted type: * * const mySchema = shape({requiredKey: string, optionalKey: optional(string)}) * type TMySchema = TypeOf * * We want the following to work: * * const myObject: TMySchema = {requiredKey: 'value'} * * This doesn't work out of the box with our definition of optional. * FixOptionalIndices defined below gives us this. */ type OptionalIndices = { [Index in keyof T]: undefined extends T[Index] ? Index : never; }[keyof T]; type RequiredIndices = { [Index in keyof T]: undefined extends T[Index] ? never : Index; }[keyof T]; type FixOptionalIndices = { [OIndex in OptionalIndices]?: T[OIndex]; } & { [RIndex in RequiredIndices]: T[RIndex]; }; export declare function shape; }>(schema: TDefnSchema): (value: unknown, opts?: TOpts) => value is FixOptionalIndices<{ [DefnIndex in keyof TDefnSchema]: ExtractTypeguard; }>; /** * This validator is equivalent to shape, except that it gives a generated type * that requires explicitly setting optional keys to undefined instead of * omitting them when they are not present. It exists for certain cases * where the typescript compiler is not smart enough to do what we want * with inferred types of generics. */ export declare function _shapeWithExplicitOptionals; }>(schema: TDefnSchema): (value: unknown, opts?: TOpts) => value is { [DefnIndex in keyof TDefnSchema]: ExtractTypeguard; }; type TDefnSchemasForTags = { [TagValueLiteral in string]: { [key: string]: Schema; } & { [tag in TTag]: Schema; }; }; type TaggedUnionDefn> = { [TagValueLiteral in keyof TDefnSchemas]: FixOptionalIndices<{ [ShapeItemKey in keyof TDefnSchemas[TagValueLiteral]]: TypeOf; }>; }[keyof TDefnSchemas]; export declare function taggedUnion>(tag: TTag, schemas: TDefnSchemas): (value: unknown, opts?: TOpts) => value is TaggedUnionDefn; export declare function array(member: Schema): (value: unknown, opts?: TOpts) => value is TMember[]; /** * Note: when defining a tuple you should specify the schema array `const` * * const tupleSchema = t.tuple([t.string, t.number] as const); * * If you don't, validation will work, but `t.typeOf` will be too permissive. * * This is due to a limitation of our current (simple) implementation. * We can eventually get to a world where this isn't required. */ export declare function tuple[]>(schema: TDefnSchema): (value: unknown, opts?: TOpts) => value is { [DefnIndex in keyof TDefnSchema]: TDefnSchema[DefnIndex] extends Schema ? ExtractTypeguard : never; } & { length: TDefnSchema['length']; }; export declare function union(left: Schema, right: Schema): (value: unknown, opts?: TOpts) => value is TLeft | TRight; export declare function intersection(left: Schema, right: Schema): (value: unknown, opts?: TOpts) => value is TLeft & TRight; export declare function unionMany>(inner: TSchema[]): (value: unknown, opts?: TOpts) => value is ExtractTypeguard; type TPluralIntersectionType = (T extends Schema ? (k: U) => void : never) extends (k: infer I) => void ? I : never; export declare function intersectMany>(inner: TSchema[]): (value: unknown, opts?: TOpts) => value is TPluralIntersectionType; export declare function literals(inners: readonly NonGenericExceptBooleans[]): (value: unknown, opts?: TOpts | undefined) => value is NonGenericExceptBooleans; export declare function optional(inner: Schema): (value: unknown, opts?: TOpts | undefined) => value is TInner | undefined; export declare function nullable(inner: Schema): (value: unknown, opts?: TOpts | undefined) => value is TInner | null; export {};