import { Arg, Type, NamedConstraints, Contra } from './Type'; import { _apply, _Type } from './apply'; import { ArrayKeys, ArrayLike, Int, Next, Slice, Subtract, Tuple } from './utils'; export { partial, partialRight, PartialRight, $partial }; export { PartialType }; /** Return a new type based upon `$T`, with `Args` already applied, expecting the constraints arguments */ type partial<$T extends _Type, Args extends Partial<$Model['constraints']>, $Model extends _Type = $T> = $T extends $Model ? Args extends unknown[] ? _partial<$T, Args> : never : never; /** A free version of `partial` */ interface $partial<$T extends _Type> extends Type<1> { type: _partial<$T, [this['arguments'][0]]>; } type _partial<$T extends _Type, Args extends ArrayLike, From extends number = Args['length'], To = Required<$T['constraints']>['length']> = PartialType<{ type: $T['type']; constraints: Slice<$T['constraints'], From, To>; names: FilterNamesLeft<$T['names'], Args>; applied: Args; direction: 'left'; }, $T>; type FilterNamesLeft = unknown & { [K in keyof T as T[K] extends Int> ? never : K]: Subtract; }; /** Return a new type based upon `$T`, with `Args` already applied to the rightmost parameters of `$T`, and expecting the remaining arguments */ type partialRight<$T extends _Type, Args extends PartialRight<$Model['constraints']>, $Model extends _Type = $T> = $T extends $Model ? _partialRight<$T, Args, Subtract['length'], Args['length']>> : never; type _partialRight<$T extends _Type, Args extends ArrayLike, To> = Slice<$T['constraints'], 0, To> extends infer Constraints ? PartialType<{ type: $T['type']; constraints: Constraints; names: FilterNamesRight<$T['names'], Constraints>; applied: Args; direction: 'right'; }, $T> : never; type FilterNamesRight = unknown & { [K in keyof T as T[K] extends Int> ? K : never]: T[K]; }; type PartialRight = T extends [unknown, ...(infer Rest)] ? PartialRight : [] | R; type Descriptor = { applied: any; direction: any; constraints: any; names: any; }; interface PartialType { [k: number]: unknown; type: _apply<$T, D['direction'] extends 'left' ? [...D['applied'], ...Complement] : [...Complement, ...D['applied']]>; names: D['names']; namedConstraints: NamedConstraints<{ names: D['names']; constraints: D['constraints']; }>; arg: Arg; constraints: D['constraints']; contra: Contra; arguments: unknown[]; } type Complement = unknown[] extends Args ? Tuple : _Complement; type _Complement = I extends L ? R : _Complement, [...R, unknown]>;