import { Tuple, ToTuple, Int, Slice, ArrayLike, ArrayKeys, OptionalKeys, IsAny, NumericKeys } from './utils'; export { Type, Input, Arg, NamedConstraints, Contra }; /** Extend `Type` with an interface to produce a free type, or use it as a type constraint. */ type Type = CreateType<{ type: Out; }, { constraints: Constraints; names: In extends Detailed ? { [K in Exclude]: GetIndex; } : None; }>; type None = {}; type Descriptor = { constraints: any; names: any; }; type Input = number | readonly unknown[] | PseudoTuple | Detailed; type PseudoTuple = { [k: number]: any; length?: number; }; type Detailed = { [k: string]: [index: number, constraint?: unknown] | number; [k: number]: never; }; interface CreateType { [k: number]: unknown; type: Out['type']; constraints: T['constraints']; contra: Contra; namedConstraints: NamedConstraints; arg: Arg; arguments: unknown[]; names: T['names']; } type Contra = any[] extends T ? IsAny extends true ? (constraints: any) => void : (constraints: { [k: number]: T[number]; }) => void : NumericKeys extends infer Keys extends number ? Int> extends infer O extends number ? (constraints: unknown & { [K in Keys as K extends O ? never : K]: T[K]; } & { [K in Keys as K extends O ? K : never]?: T[K]; }) => void : never : never; type NamedConstraints>> = { [K in keyof T['names'] as T['names'][K] extends O ? never : K]: T['constraints'][T['names'][K]]; } & { [K in keyof T['names'] as T['names'][K] extends O ? K : never]?: T['constraints'][T['names'][K]]; }; type _Type = { [k: number]: unknown; constraints: ArrayLike; names: { [k: string]: number; }; }; type Arg, R extends PropertyKey = Exclude>, O>> = { [K in Norm as `${K & number}` | K]: ArgVal; } & { [K in Norm as `${K & number}` | K]?: ArgVal; }; type FindOptionalKeys>> = O | (keyof { [K in keyof Names as Names[K] extends O ? K : never]: never; }); type ArgVal = K extends `${number}` | number ? Int extends infer Key extends number ? GetValue : never : K extends string ? GetValue : never; type GetValue = This['constraints'][I] extends infer Constraint ? This[I] extends Constraint ? This[I] : Constraint & This[I] : never; type Norm = T extends `${number}` ? Int : T; type Unconstrained = { [k: number]: any; }; type Variadic = { [k: number]: unknown; }; type Constraints = IsAny extends true ? Unconstrained : unknown[] extends T ? IsAny[number]> extends true ? Unconstrained : Variadic : readonly unknown[] extends T ? Variadic : T extends readonly unknown[] ? T : T extends number ? number extends T ? Variadic : Tuple : T extends Detailed ? DetailedToConstraints : T extends PseudoTuple ? T extends ArrayLike ? Slice : ToTuple : Variadic; type DetailedToConstraints = ToTuple<{ [K in keyof T as GetIndex]: GetConstraint; }>; type GetIndex = Exclude; type GetConstraint = Exclude extends [any, infer C] ? C : unknown;