Currying 1
Challenge
TypeScript 4.0 is recommended in this challenge
Currying is the technique of converting a function that takes multiple arguments into a sequence of functions that each take a single argument.
For example:
const add = (a: number, b: number) => a + b;
const three = add(1, 2);
const curriedAdd = Currying(add);
const five = curriedAdd(2)(3);
The function passed to Currying may have multiple arguments, you need to correctly type it.
In this challenge, the curried function only accept one argument at a time. Once all the argument is assigned, it should return its result.
Solution
Zur Lösung dieser Aufgabe hilft es Hilfstypen zu definieren, die man anschließend kombinieren kann, um das richtige Ergebnis zu erhalten:
/*
Extrahiert den Rückgabewert aus einer Funktion
(a: string, b: string) => true // boolean
*/
type FnReturn<T extends (...args: any[]) => any> = T extends (
...args: infer U
) => infer R
? R
: never;
/*
Gibt alle Parameter / Argumente einer Funktion als Array zurück. Man muss diesen Hilfstyp nicht zwingend selber definieren,
man kann auch den vorhanden Typ Parameters<T> nutzen
(a: string, b: string) => true : [a:string, b: string]
*/
type FnArgs<T> = T extends (...args: infer U) => any ? U : never;
/*
Den finalen Typen erhalten wir, indem wir durch den Array von Parameters iterieren und solange den Typ rekursiv wieder aufrufen, bis der Array leer ist
*/
type CurryFunction<
T extends (...args: any[]) => any,
P extends any[] = FnArgs<T>
> = P extends [infer H, ...infer Rest]
? (args: H) => CurryFunction<T, Rest>
: FnReturn<T>;
declare function Currying<T>(
fn: T
): T extends (...args: any[]) => any ? CurryFunction<T> : never;