UNPKG

narrow-minded

Version:

Easy typeof validations with sophisticated TypeScript inference.

105 lines 4.06 kB
/** * Includes all values that can be returned by a `typeof` expression. */ export type Primitive = 'string' | 'number' | 'bigint' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function'; /** * Reverse mapping `Primitive` type to the string that represents each primitive. */ export type UnPrimitive<N> = N extends 'string' ? string : N extends 'number' ? number : N extends 'bigint' ? bigint : N extends 'boolean' ? boolean : N extends 'symbol' ? symbol : N extends 'undefined' ? undefined : N extends 'object' ? object : N extends 'function' ? Function : unknown; /** * Recursive type of an array Narow schema. */ export type NarrowerArr = Array<Primitive | NarrowerObj | NarrowerArr | NarrowerSome>; /** * Recursive type of an object Narow schema */ export interface NarrowerObj { [k: string]: Primitive | NarrowerArr | NarrowerObj | NarrowerSome; } /** * This is the type that specifies a narrowed structure. The simplest form is a Primitive string, * which will validate using a `typeof` comparison. Deeper structures can be defined using objects * and arrays that will be validated recursively. * * @example * // An array of mixed strings and numbers: * ['string', 'number'] * * // A deep object: * { * n: 'number', * child: { * word: 'string' * }, * things: [ * ['number'], * 'boolean' * ], * } */ export type Narrower = Primitive | NarrowerArr | NarrowerObj | NarrowerSome; /** * This attempts to infer a narrowed type based on a Narrow schema, which results in nice types * within conditional blocks. If inference is not possible, the type remains `unknown`. * * An empty array as a schema is a special case: TypeScript wants to assume the contained type is * `never` (the array is empty, so the contents have no type) but this is not useful in practice, so * the content type is also replaced with `unknown`. */ export type UnNarrow<N> = N extends Primitive ? UnPrimitive<N> : N extends Array<never> ? Array<unknown> : N extends Array<infer N2> ? N extends NarrowerSome ? UnNarrow<N2> : Array<UnNarrow<N2>> : N extends Record<keyof N, infer _N2> ? { [k in keyof N]: UnNarrow<N[k]>; } : unknown; /** * Unique symbol that is used to decorate an array of Narrower schemas. */ export declare const SOME: unique symbol; /** * Supplemental type for `SOME` decorated arrays. Note that this _does not_ intersect with an * `Array` type of any kind, because the array type must be kept generic in order for inference and * un-narrowing to work. */ export type NarrowerSome = { [SOME]: true; }; /** * Decorates a narrower array to indicate narrowing should use the array as a * set of options instead of asserting the value is an actual array. * * @example * narrow(some('number'), 1) //=> true * narrow({ optional: some('string', 'undefined') }), { optional: 'yep' }) //=> true * narrow({ optional: some('string', 'undefined') }), {}) //=> true * * @param narrowers The Narrower sub-schemas that the value must be one of. * @returns An array with the SOME symbol set to true. */ export declare const some: <NA extends NarrowerArr>(...narrowers: NA) => NA & NarrowerSome; /** * Type guard for `NarrowerArr` type. * @param n Narrower schema * @returns true if `n` is an array and is _not_ `SOME` decorated */ export declare const isNarrowerArr: (n: Narrower) => n is NarrowerArr & { [SOME]: never; }; /** * Type guard for `NarrowerSome` type. * @param n Narrower schema * @returns true if `n` is a `SOME` decorated array. */ export declare const isNarrowerSome: (n: Narrower) => n is NarrowerArr & NarrowerSome; /** * Type guard for `NarrowerObj` type * @param n Narrower schema * @returns true if `n` is an indexable object. */ export declare const isNarrowerObj: (n: Narrower) => n is NarrowerObj & { [SOME]: never; }; /** * Type guard for an indexable object * @param u Any value * @returns true if `u` is a non-array, non-null object. */ export declare const isRecordObj: (u: unknown) => u is Record<string, unknown>; //# sourceMappingURL=schema.d.ts.map