stnl
Version: 
A simple, opinionated type validator built for performance
142 lines (141 loc) • 4.39 kB
TypeScript
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 {};