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;