narrow-minded
Version:
Easy typeof validations with sophisticated TypeScript inference.
105 lines • 4.06 kB
TypeScript
/**
* 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