UNPKG

type-assurance

Version:

Lightweight type guards and assertions

86 lines (85 loc) 3.46 kB
/** * Marker for optional properties. */ declare const OPTIONAL: "type-assurance:optional"; /** * Runtime type definition. */ export type Schema = StringConstructor | NumberConstructor | BooleanConstructor | ReadonlyArray<Schema> | { [prop: string]: Schema; } | (new (...args: any) => any) | ((v: unknown) => boolean) | string | number | boolean | null | undefined; /** * Type to get the actual type from a schema. */ export type TypeFromSchema<T> = T extends StringConstructor ? string : T extends NumberConstructor ? number : T extends BooleanConstructor ? boolean : T extends ReadonlyArray<Schema> ? { [P in keyof T]: TypeFromSchema<T[P]>; } : T extends { [key: string]: Schema; } ? Expand<OptionalProps<T> & RequiredProps<T>> : T extends new (...args: any) => infer R ? R : T extends (v: unknown) => v is infer R ? R : T; /** * Expand mapped types for better readability. * See https://github.com/microsoft/TypeScript/issues/47980 */ type Expand<T> = T extends unknown ? { [K in keyof T]: T[K]; } : never; /** * Extract only the optional props of a schema. */ type OptionalProps<T> = { -readonly [K in keyof T as T[K] extends { [OPTIONAL]: true; } ? K : never]?: TypeFromSchema<T[K]>; }; /** * Extract only the required props of a schema. */ type RequiredProps<T> = { -readonly [K in keyof T as T[K] extends { [OPTIONAL]: true; } ? never : K]: TypeFromSchema<T[K]>; }; /** * Type guard to check if a value is compatible with a given schema. */ export declare function is<const T extends Schema>(value: unknown, schema: T): value is TypeFromSchema<T>; /** * Compares a value to a schema and returns all property paths * where the data does not match the specified type. */ export declare function diff<const T extends Schema>(value: unknown, schema: T, path?: string): Array<string>; /** * Creates a type guard that checks if a value matches the given schema. */ export declare function typeGuard<const T extends Schema>(schema: T): (value: unknown) => value is TypeFromSchema<T>; /** * Creates a type guard that checks if a value matches any of the given schemas. */ export declare function union<T extends Schema[]>(...schemas: T): (v: unknown) => v is TypeFromSchema<T[number]>; /** * Creates a type guard that checks if a value either matches the given schema or is undefined. * The returned function is marked with the `type-assurance:optional` marker – when used as value inside an * object, the property will become optional. */ export declare function optional<T extends Schema>(schema: T): ((v: unknown) => v is TypeFromSchema<T> | undefined) & { [OPTIONAL]: true; }; /** * Type guard that always returns `true`. Can be used to create schemas * where the type of a property does not matter. */ export declare function unknown(v: unknown): v is unknown; /** * Asserts that a value matches a given schema. * @throws TypeError if the value does not match the schema. */ export declare function assert<T extends Schema>(value: unknown, schema: T): asserts value is TypeFromSchema<T>; /** * Valid Record keys */ export type RecordKeys = StringConstructor | NumberConstructor | string | number; /** * Creates a type guard that checks if a value matches a given Record<K, V>. */ export declare function record<const K extends RecordKeys, const V extends Schema>(key: K, value: V): (v: unknown) => v is Record<TypeFromSchema<K>, TypeFromSchema<V>>; export {};