UNPKG

stnl

Version:

A simple, opinionated type validator built for performance

142 lines (141 loc) 4.39 kB
import type { LLen } from "./limit.js"; type Evaluate<T> = { [K in keyof T] : T[K] } & {}; declare const _: unique symbol; type _ = typeof _; export interface IType< I extends number = number, T = any, R = any > extends Ref<R> { 0: I; [_]: T; } export type TLoadedType = IType<number, any, never>; export type TInfer<T extends TLoadedType> = T[_]; type TypeDict = Record<string, IType>; type InferTypeList<T extends IType[]> = T extends [infer A extends IType, ...infer B extends IType[]] ? [A[_], ...InferTypeList<B>] : []; interface NullableMap { 4: 5; 10: 11; 12: 13; 14: 15; 16: 17; 18: 19; 20: 21; 22: 23; } type ToNullable<T extends IType<keyof NullableMap>> = IType<NullableMap[T[0]], T[_] | null, T[""]>; export type TInt = IType<0, number, never>; export type TFloat = IType<2, number, never>; export type TString = IType<4, string, never>; export type TBool = IType<6, boolean, never>; export type TAny = IType<8, unknown, never>; type CUnion = [string, string, ...string[]]; export type TUnion<T extends CUnion> = IType<10, T[number], never>; type CConst = number | string | boolean; export type TConst<T extends CConst> = IType<12, T, never>; export type TList<T extends IType> = IType<14, T[_][], T[""]>; export type TDict< Required extends TypeDict, Optional extends TypeDict > = IType<16, Evaluate<{ [K in keyof Required] : Required[K][_] } & { [K in keyof Optional]? : Optional[K][_] }>, (Required[keyof Required] | Optional[keyof Optional])[""]>; type CTuple = [IType, IType, ...IType[]]; export type TTuple<T extends CTuple> = IType<18, InferTypeList<T>, T[number][""]>; export type TTag< I extends string, T extends TypeDict > = IType<20, Evaluate<{ [K in keyof T] : { [N in I] : K } & T[K][_] }[keyof T]>, T[keyof T][""]>; interface Ref<T> { "": T; } export type SelfRef = Ref<"">; export type TSelf = TRef<"">; export type TRef<T> = IType<22, Ref<T>, T>; type ResolveRef< Root, Map, Type > = Type extends SelfRef ? ResolveRef<Root, Map, Root> : Type extends Ref<infer K extends keyof Map> ? ResolveRef<Root, Map, Map[K]> : Type extends Record<string, any> | any[] ? { [K in keyof Type] : ResolveRef<Root, Map, Type[K]> } : Type; export type TScope< T extends IType, R extends Record<any, IType | undefined> > = IType<24, ResolveRef<T[_], { [K in keyof R] : (R[K] & {})[_] }, T[_]>, Exclude<T[""], "" | keyof R>>; export declare const int: TInt; export declare const float: TFloat; export declare const string: TString; export declare const bool: TBool; export declare const any: TAny; /** * Create a nullable type * @param t */ export declare const nullable: <const T extends IType<keyof NullableMap>>(t: T) => ToNullable<T>; /** * Create an union schema * @param l * @returns */ export declare const union: <const T extends CUnion>(l: T) => TUnion<T>; /** * Create a constant schema * @param t * @param nullable */ export declare const value: <const T extends CConst>(t: T) => TConst<T>; /** * Create a list type */ export declare const list: <const T extends IType>(...args: [type: T, ...LLen[]]) => TList<T>; /** * Create a dict type * @param required - Required props * @param optional - Optional props */ export declare const dict: < Required extends TypeDict | null, Optional extends TypeDict = {} >(required: Required, optional?: Optional) => TDict<Required extends null ? {} : Required, Optional>; /** * Create a tuple type * @param t */ export declare const tuple: <T extends CTuple>(t: T) => TTuple<T>; /** * Create a tagged union type * @param tag * @param map */ export declare const tag: < const I extends string, T extends Record<string, TDict<TypeDict, TypeDict>> >(tag: I, map: T) => TTag<I, T>; /** * Create a reference to a type * @returns */ export declare const ref: <const T extends string>(t: T) => TRef<T>; /** * Reference to the scope type */ export declare const self: TSelf; /** * Nullable reference to the type of the upper scope */ export declare const nullable_self: ToNullable<TSelf>; interface FScope { < const T extends IType, const R extends { [K in T[""]]? : IType } >(t: T, r: R): TScope<T, R>; <const T extends IType>(t: T): TScope<T, {}>; } /** * Resolve some unresolved references of a type */ export declare const scope: FScope; /** * Create a type module * @param t */ export declare const module: <const T extends Record<string, IType>>(t: T) => { [K in keyof T] : TScope<T[K], T> }; export {};