Currying is a technique in functional programming where a function that takes multiple arguments is transformed into a sequence of functions, each taking a single argument. In TypeScript, you can implement currying using function overloads and generics. Here's a simple example:
typescripttype Curry<T extends any[], R> =
<P extends Partial<T>>(...args: P) => P extends T
? T['length'] extends P['length']
? R
: Curry<
Exclude<T, P>,
R
>
: Curry<T, R>;
function curry<T extends any[], R>(fn: (...args: T) => R): Curry<T, R> {
return (...args: any[]) =>
args.length >= fn.length
? fn(...args as T)
: curry((fn.bind(null, ...args) as unknown) as (...args: T) => R);
}
// Example usage:
function add(a: number, b: number, c: number): number {
return a + b + c;
}
const curriedAdd = curry(add);
console.log(curriedAdd(1)(2)(3)); // Output: 6
console.log(curriedAdd(1, 2)(3)); // Output: 6
console.log(curriedAdd(1)(2, 3)); // Output: 6
console.log(curriedAdd(1, 2, 3)); // Output: 6
This curry
function takes another function fn
as an argument and returns a curried version of that function. The Curry
type is a generic type that takes an array of argument types T
and a return type R
. The curry
function uses TypeScript's function overloads and generics to handle the currying logic.
In the example, the add
function is curried using the curry
function, and then you can call the curried function with either one, two, or three arguments. The result is a partially applied function that can be invoked with the remaining arguments at a later time.