awesome-typescript icon indicating copy to clipboard operation
awesome-typescript copied to clipboard

「重学TS 2.0 」TS 练习题第二十题

Open semlinker opened this issue 4 years ago • 16 comments

实现一个 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

请在下面评论你的答案。

semlinker avatar Sep 17 '21 14:09 semlinker

//求指点感觉不是很对

type Curry<
  F extends (...args: any[]) => any,
  P extends any[] = Parameters<F>,
  R = ReturnType<F>
> = P extends [infer A, ...infer B]
  ? B extends []
    ? (...args: [A]) => R
    : (...args: [A]) => Curry<(...args: B) => R>
  : () => R;
//
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

sunboyZgz avatar Sep 17 '21 15:09 sunboyZgz

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

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

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

zhaoxiongfei avatar Sep 18 '21 00:09 zhaoxiongfei

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

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

加强版本,保留原参数名

type FirstAsArray<T extends any[]> = 
T extends [...infer A, infer B, infer C] 
  ? A extends []
    ? T extends [...infer A, infer B] ? A : never
    : T extends [...infer A, infer B] ? FirstAsArray<A> : never
  : T;

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

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

Honye avatar Sep 22 '21 07:09 Honye

保留参数名

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

  type LastAsArray<T extends any[]> = T extends [infer A, ...infer B] ? B extends [] ? T : LastAsArray<B> : []
  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) => (...arg: 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> //  (arg_0: number) => (b: string) => Date
  type F3 = Curry<(a: number, b: string, c: boolean) => Date> // (a: number) => (b: string) => (c: boolean) => Date

ln0y avatar Sep 23 '21 12:09 ln0y

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

type Curry<
F extends (...args: any[]) => any,
P extends any[] = Parameters<F>,
R = ReturnType<F>
> = P extends [infer A, ...infer B]
  ? B["length"] extends 0
    ? F
    : (arg: A) => Curry<(...args: B) => R>
  : 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

解题思路: 没啥特别要说的,依然是利用 extends 来探测参数的长度,利用递归逐渐减少参数个数。算法思想是是减治。

zhaoxiongfei avatar Oct 02 '21 07:10 zhaoxiongfei

type Curry<
    F extends (...args: any[]) => any,
    P extends any[] = Parameters<F>,
    R = ReturnType<F>
    > = P extends [infer U, ...infer Arg] ? (arg: U) => Curry<F, Arg, R> : P extends [] ? () => R : never

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

Mrlgm avatar Oct 02 '21 15:10 Mrlgm

type Curry<F extends ((...args: any[]) => any)> = F extends ((arg_0: infer Arg, ...restArg: infer Rests) => any) ? (
    Rests extends [] ? F : ((arg: Arg) => Curry<(...args: Rests) => ReturnType<F>>)
) : never

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

safarishi avatar Oct 06 '21 14:10 safarishi

//求指点感觉不是很对

type Curry<
  F extends (...args: any[]) => any,
  P extends any[] = Parameters<F>,
  R = ReturnType<F>
> = P extends [infer A, ...infer B]
  ? B extends []
    ? (...args: [A]) => R
    : (...args: [A]) => Curry<(...args: B) => R>
  : () => R;
//
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

A 不需要用 [] 包起来

safarishi avatar Oct 06 '21 15:10 safarishi

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

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

Flavour86 avatar Oct 22 '21 07:10 Flavour86

柯里化 是啥意思

rookiecdn avatar Nov 23 '21 01:11 rookiecdn

type Curry<F extends (...any: any[]) => any, A extends any[] = Parameters<F>> = 
    A extends [one: infer One, ...rest: infer Rest]
        ? A extends [one: any]
            ? F
            : (a: One) => Curry<(...arg: Rest) => ReturnType<F>>
        : F

yang131323 avatar Jan 26 '22 09:01 yang131323

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

SSSzhao avatar Feb 28 '22 09:02 SSSzhao

保留参数名

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

  type LastAsArray<T extends any[]> = T extends [infer A, ...infer B] ? B extends [] ? T : LastAsArray<B> : []
  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) => (...arg: 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> //  (arg_0: number) => (b: string) => Date
  type F3 = Curry<(a: number, b: string, c: boolean) => Date> // (a: number) => (b: string) => (c: boolean) => Date

这个为什么可以保留参数名啊

waleiwalei avatar Mar 15 '22 08:03 waleiwalei


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

LiuerQin avatar Jun 30 '22 03:06 LiuerQin

柯里化 是啥意思

函数返函数 () => () => () => ''

dolphin0618 avatar Jul 10 '22 04:07 dolphin0618

type Curry< F extends (...args: any[]) => any, P extends any[] = Parameters<F>, R = ReturnType<F> > = P extends [infer P0, ...infer P1] ? (arg: P0) => P['length'] extends 1 ? R : Curry<((...args:P1)=>R)> : 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

dingzc2450 avatar Jul 22 '22 05:07 dingzc2450