20、重学TS-第二十题

78 阅读1分钟

实现一个 Curry 工具类型,用来实现函数类型的柯里化处理。具体的使用示例如下所示:

type Curry<
  F extends (...args: any[]) => any,
  P extends any[] = Parameters<F>, 
  R = ReturnType<F> 
> = // 你的实现代码

type F0 = Curry<() => Date>; // () => Date
type F1 = Curry<(a: number) => Date>; // (arg: number) => Date
type F2 = Curry<(a: number, b: string) => Date>; //  (arg_0: number) => (b: string) => Date

最开始我写的是

type Curry<
  F extends (...args: any[]) => any,
  P extends any[] = Parameters<F>,
  R = ReturnType<F>
> = P extends [...infer A, infer B]
? A extends []
  ? F
  : Curry<(...args: A) => (args: B) => R>
: F

这样可以实现基本功能,但是有一个缺点,就是无法保留原始的参数名 那么要想保留原始的参数名,就需要将B转为一个数组,即下面的LastAsArray,这样最终参数名得以保留

type LastAsArray<T extends any[]> = T extends [infer A, ...infer B] ? B extends [] ? T : LastAsArray<B> : T;
type Curry<
  F extends (...args: any[]) => any,
  P extends any[] = Parameters<F>,
  R = ReturnType<F>
> = P extends [...infer A, infer B]
? A extends []
  ? F
  : Curry<(...args: A) => (...args: LastAsArray<P>) => R>
: F

type F0 = Curry<() => Date>; // () => Date
type F1 = Curry<(a: number) => Date>; // (arg: number) => Date
type F2 = Curry<(a: number, b: string) => Date>; //  (a: number) => (b: string) => Date