import { Contra, NamedConstraints } from './Type'; import { ArrayLike, Next, IsOptional, Mappable, Union2Tuple, Int } from './utils'; export { From }; type Named = ({ [k: PropertyKey]: string; } | undefined)[]; type None = {}; /** Create a new `Type` based upon a Mappable `T`. * * Optionally take a tuple `Args` to specify which fields to turn into a parameter and in what order they must be applied. Parameters can be set to be optional. Named parameters are created automatically for object types, they can be renamed. * * */ type From, Args extends readonly (keyof T | undefined)[] | Named = never> = ([ Args ] extends [never] ? (T extends unknown[] ? GetIndices : Union2Tuple) extends infer K ? { constraints: PseudoTuple; names: None; keys: K; } : never : Args extends Named ? { constraints: ToConstraints; names: GetNames; keys: GetKeys; } : { constraints: PseudoTuple; names: Args extends (string | undefined)[] ? GenerateNames : {}; keys: Required; }) extends infer D extends Descriptor ? FromTemplate<{ type: T; }, D> : never; type Descriptor = { constraints: any; names: any; keys: any; }; interface FromTemplate { [k: number]: unknown; type: T['type'] extends infer Type ? unknown[] extends this['arguments'] ? Type : { [K in keyof Type]: Value, D['constraints']>; } : never; namedConstraints: NamedConstraints; names: D['names']; constraints: D['constraints']; contra: Contra; arg: any; arguments: unknown[]; } type GetIndices = { [K in keyof T]-?: K; }; export type Value = [ I ] extends [never] ? T : IsOptional extends true ? This[I & number] extends undefined ? T : This[I & number] : This[I & number]; export type IndexOf['length'], I = 0> = I extends L ? never : [T] extends [`${Ts[I & number]}`] ? I : IndexOf>; type PseudoTuple = { [K in keyof Keys]: Exclude; }; type ToConstraints = { [K in keyof Args]: T[keyof (Args[K] & {}) & keyof T]; }; type GetKeys> = { [K in keyof R]: keyof R[K]; }; type GetNames = Required> = unknown & { [K in keyof T as T[K & `${number}`][keyof T[K]]]: Int; }; type GenerateNames = unknown & { [K in Exclude as Args[K] & string]: Int; };