type Head = T extends [any, ...any[]] ? T[0] : never; type Tail = ((...t: T) => any) extends ((_: any, ...tail: infer TT) => any) ? TT : []; type HasTail = T extends ([] | [any]) ? false : true; type Last = { 0: Last>; 1: Head; }[HasTail extends true ? 0 : 1]; type Length = T['length']; type Prepend = ((head: E, ...args: T) => any) extends (( ...args: infer U ) => any) ? U : T; type Drop = { 0: Drop, Prepend>; 1: T; }[Length extends N ? 1 : 0]; type Cast = X extends Y ? X : Y; type Pos = Length; type Next = Prepend; type Prev = Tail; type Reverse = { 0: Reverse], R>, Next>; 1: R; }[Pos extends Length ? 1 : 0]; type Concat = Reverse< Reverse extends infer R ? Cast : never, T2 >; type Append = Concat; type GapOf = T1[Pos< I >] extends Placeholder ? Append], TN> : TN; type GapsOf = { 0: GapsOf extends infer G ? Cast : never, Next>; 1: Concat, T2> extends infer D ? Cast : never>; }[Pos extends Length ? 1 : 0]; type PartialGaps = { [K in keyof T]?: T[K] | Placeholder }; type CleanedGaps = { [K in keyof T]: NonNullable }; type Gaps = CleanedGaps>; type Curry = ( ...args: Cast>>, any[]> ) => GapsOf> extends [any, ...any[]] ? Curry< (...args: GapsOf> extends infer G ? Cast : never) => ReturnType > : ReturnType; export type Placeholder = Symbol | number; export const __: Placeholder; export type Handler = (...args: any[]) => any; export type Curried = Curry & { arity: number; fn: Fn; }; export function curry(fn: Fn): Curried; export function curry(fn: Fn, arityOverride: number): Handler; export function isPlaceholder(value: any): value is Placeholder; export function uncurry(curried: Curried): Fn; export default curry;