Skip to content

Instantly share code, notes, and snippets.

@trvswgnr
Last active June 19, 2024 22:20
Show Gist options
  • Save trvswgnr/8d4338ca6d239cf3096a87e6e84f1ded to your computer and use it in GitHub Desktop.
Save trvswgnr/8d4338ca6d239cf3096a87e6e84f1ded to your computer and use it in GitHub Desktop.
partial application in typescript
export default function createPartialApplication<T extends any[], R>(
fn: (...args: T) => R,
): PartialApplication<T, R> {
return function accumulator(...args1: any[]): any {
return args1.length >= fn.length
? fn(...(args1 as T))
: (...args2: any[]) => accumulator(...args1.concat(args2));
};
}
type PartialApplication<T extends readonly any[], R> = <A extends Partial<T>>(
...args: A
) => Length<A> extends Length<T>
? R
: PartialApplication<ShiftN<T, Length<A>>, R>;
type Length<T extends readonly any[]> = T["length"];
type ShiftNMap<T extends readonly any[]> = {
0: T;
1: ShiftOne<T>;
2: ShiftOne<ShiftOne<T>>;
3: ShiftOne<ShiftOne<ShiftOne<T>>>;
4: ShiftOne<ShiftOne<ShiftOne<ShiftOne<T>>>>;
5: ShiftOne<ShiftOne<ShiftOne<ShiftOne<ShiftOne<T>>>>>;
};
type ShiftN<T extends readonly any[], N> = N extends keyof ShiftNMap<T>
? ShiftNMap<T>[N]
: N extends number
? any[]
: never;
type ShiftOne<T extends readonly any[]> = T extends [any, ...infer U]
? U
: never;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment