Skip to content

Instantly share code, notes, and snippets.

@lesleh
Last active April 10, 2023 21:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lesleh/fa8289974b65f3d7b9a5bbf55f5028cf to your computer and use it in GitHub Desktop.
Save lesleh/fa8289974b65f3d7b9a5bbf55f5028cf to your computer and use it in GitHub Desktop.
Function to auto-curry another function, with strong typing
interface Curry {
<T1, R>(func: (t1: T1) => R): CurriedFunction1<T1, R>;
<T1, T2, R>(func: (t1: T1, t2: T2) => R): CurriedFunction2<T1, T2, R>;
<T1, T2, T3, R>(func: (t1: T1, t2: T2, t3: T3) => R): CurriedFunction3<
T1,
T2,
T3,
R
>;
<T1, T2, T3, T4, R>(
func: (t1: T1, t2: T2, t3: T3, t4: T4) => R
): CurriedFunction4<T1, T2, T3, T4, R>;
<T1, T2, T3, T4, T5, R>(
func: (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5) => R
): CurriedFunction5<T1, T2, T3, T4, T5, R>;
(func: (...args: any[]) => any): (...args: any[]) => any;
}
interface CurriedFunction1<T1, R> {
(): CurriedFunction1<T1, R>;
(t1: T1): R;
}
interface CurriedFunction2<T1, T2, R> {
(): CurriedFunction2<T1, T2, R>;
(t1: T1): CurriedFunction1<T2, R>;
(t1: T1, t2: T2): R;
}
interface CurriedFunction3<T1, T2, T3, R> {
(): CurriedFunction3<T1, T2, T3, R>;
(t1: T1): CurriedFunction2<T2, T3, R>;
(t1: T1, t2: T2): CurriedFunction1<T3, R>;
(t1: T1, t2: T2, t3: T3): R;
}
interface CurriedFunction4<T1, T2, T3, T4, R> {
(): CurriedFunction4<T1, T2, T3, T4, R>;
(t1: T1): CurriedFunction3<T2, T3, T4, R>;
(t1: T1, t2: T2): CurriedFunction2<T3, T4, R>;
(t1: T1, t2: T2, t3: T3): CurriedFunction1<T4, R>;
(t1: T1, t2: T2, t3: T3, t4: T4): R;
}
interface CurriedFunction5<T1, T2, T3, T4, T5, R> {
(): CurriedFunction5<T1, T2, T3, T4, T5, R>;
(t1: T1): CurriedFunction4<T2, T3, T4, T5, R>;
(t1: T1, t2: T2): CurriedFunction3<T3, T4, T5, R>;
(t1: T1, t2: T2, t3: T3): CurriedFunction2<T4, T5, R>;
(t1: T1, t2: T2, t3: T3, t4: T4): CurriedFunction1<T5, R>;
(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5): R;
}
const curry: Curry = (fn) => {
const arity = fn.length;
return function $curry(...args) {
if (args.length >= arity) {
return fn(...args);
}
return $curry.bind(null, ...args);
};
};
// Example
const fn = curry(
(a: number, b: number, c: number, d: number, e: number) => a + b + c + d + e
)
console.log(fn(1)(2, 3, 4, 5));
console.log(fn(1, 2)(3, 4, 5));
console.log(fn(1, 2, 3)(4, 5));
console.log(fn(1, 2, 3, 4, 5));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment