type-challenges / type-challenges

Collection of TypeScript type challenges with online judge
https://tsch.js.org/
MIT License
43.31k stars 4.7k forks source link

17 - Currying 1 #6282

Open dagda1 opened 2 years ago

dagda1 commented 2 years ago
type Curry<P, R> = P extends [infer H, ...infer T] ? (p: H) => Curry<T, R> : R;

declare function Currying<F>(fn: F): F extends (...P: infer A) => infer R ? Curry<A, R> : never;
HenryZhang-ZHY commented 1 year ago

Good answer! It works for curried1 and curried2, but not for curried 3 (typeof curried3 = true).

const curried1 = Currying((a: string, b: number, c: boolean) => true)
const curried2 = Currying((a: string, b: number, c: boolean, d: boolean, e: boolean, f: string, g: boolean) => true)
const curried3 = Currying(() => true)

type cases = [
  Expect<Equal<
    typeof curried1, (a: string) => (b: number) => (c: boolean) => true
  >>,
  Expect<Equal<
    typeof curried2, (a: string) => (b: number) => (c: boolean) => (d: boolean) => (e: boolean) => (f: string) => (g: boolean) => true
  >>,
  Expect<Equal<typeof curried3, () => true>>,
]

I have updated your solution with the following code and all test cases have passed.

type Curry<P, R> = P extends [infer H, ...infer T] ? (p: H) => Curry<T, R> : R;

declare function Currying<F>(fn: F):
  F extends (...P: infer A) => infer R
  ? A extends [] ? () => R : Curry<A, R>
  : never;