Implement a more permissive variant of currying. Classic curry forces one argument per call: curry(fn)(a)(b)(c). This version is flexible — the caller can pass any number of arguments at each step, and the curried function keeps collecting until it has enough to invoke the original. So curry(fn)(a, b)(c), curry(fn)(a)(b, c), and curry(fn)(a, b, c) all produce the same result.
The "arity" of a function is fn.length — the count of named parameters in its declaration. Your job is to keep returning a new function that accumulates arguments until you have at least fn.length of them, then call fn with the collected args.
// Returns a curried wrapper that gathers args across any number of calls
// until fn.length args have been collected, then invokes fn(...args).
function curry(fn: (...args: any[]) => any): (...args: any[]) => any;
const sum3 = (a, b, c) => a + b + c;
const curried = curry(sum3);
curried(1)(2)(3); // 6 — one arg at a time
curried(1, 2, 3); // 6 — all at once
curried(1, 2)(3); // 6 — 2 then 1
curried(1)(2, 3); // 6 — 1 then 2
const greet = (greeting, name) => `${greeting}, ${name}!`;
const c = curry(greet);
c('Hello')('world'); // "Hello, world!"
c('Hi', 'Ada'); // "Hi, Ada!"
// fn.length === 0 — there's nothing to collect, so the curried form
// just calls fn() on first invocation.
curry(() => 42)(); // 42
fn.length for the arity. That's the count of named parameters before any default values or rest params. Don't try to be cleverer than fn.length.fn early. As long as the total collected arguments is less than fn.length, return another curried function. Only when the count reaches fn.length (or more) do you call fn.fn.length (e.g. curried(1, 2, 3, 4) for a 3-arg fn), forward all of them to fn. The spec is "call once you have enough", not "trim to exactly fn.length".this. When invoked with .call(ctx, ...) or .apply(ctx, ...), the original fn must receive that same this. A regular function (not an arrow) for the returned wrapper handles this naturally.curry(() => 42) must return a function that, when called with no args, returns 42.curried(1)(2) must not affect a sibling curried(10)(20).