This content was inpired by two great talks. I've put the links for them in References section.
type AnyFunc = (...args: any[]) => any
type AllParams<T> = T extends (...args: infer A) => any ? A : never
type FirstParam<T extends any[]> = T extends [any, ...any[]]
? T[0]
: never
type OtherParams<T extends any[]> = ((...things: T) => any) extends (
first: any,
...others: infer R
) => any
? R
: []
type Remainder<T extends AnyFunc> = T extends (
...args: infer A
) => infer R
? A extends [infer P1, infer P2]
? (b: P2) => R
: A extends [infer P1, infer P2, infer P3]
? (b: P2) => (c: P3) => R
: A extends [infer P1, infer P2, infer P3, infer P4]
? (b: P2) => (c: P3) => (d: P4) => R
: never
: never
type Curried<T extends AnyFunc> = T extends (...args: infer A) => infer R
? (a: FirstParam<A>) => Remainder<T>
: never
const curry = <T extends AnyFunc>(
fn: T,
arity = fn.length,
...args
): Curried<T> =>
arity <= args.length
? fn(...args)
: (...argz) => curry(fn, arity, ...args, ...argz)
const doSomething = (first: number, second: string, third: Record<string, unknown>) => {
return 1
}
const curriedDoSomething = curry(doSomething) // <- (a: number) => (b: string) => (c: Record<string, unknown>) => number
This content is inspired by these two talks.
Not Your Mother's TDD: Type Driven Development in TypeScript - G Gilmour & R Gibson - NIDC2020 Lambda World 2018 - Functional Lenses in JavaScript - Flavio Corpa
This article (link down below) presents an even better solution. Much more complex I should say, but this is why we are here: to play with fire. So, besides the great learning resource, it includes a more flexible curry version. You could do something like:
const createPerson = (name: string, age: number, single: boolean, ...nicknames: string[]) => true
const curriedCreatePerson = curry(createPerson)
const test1 = curriedCreatePerson('Jane', 26)(true, 'JJ', 'Jini') // 👍 boolean
const test2 = curriedCreatePerson('Jane')(26, true, 'JJ', 'Jini') // 👍 boolean
const test3 = curriedCreatePerson('Jane')(26)(true, 'JJ', 123) // 💥 error