【问题标题】:How to type a curried `map`?如何输入咖喱“地图”?
【发布时间】:2020-02-01 19:00:40
【问题描述】:

我正在尝试在 TypeScript 中键入一个 curried map 函数。这是等效的 JavaScript:

const double = n => n * 2;
const map = f => arr => arr.map(f);
const doubleArr = map(double);

console.log(doubleArr([1, 2, 3]));
// ↳ [2, 4, 6]

理想情况下,TypeScript 应该能够推断,在将 double 提供给 map 之后,doubleArray 接受一个数字数组并返回一个数字数组。

这是我尝试过的:

const double = (n: number) => n * 2;
const map = (f: Function) => (arr: Array<any>) => arr.map(f);

但是,TypeScript 在map 内部抱怨f

Argument of type 'Function' is not assignable to parameter of type '(value: any, index: number, array: any[]) => unknown'.
  Type 'Function' provides no match for the signature '(value: any, index: number, array: any[]): unknown'.

你会如何在 TypeScript 中输入这个函数?

【问题讨论】:

    标签: typescript currying map-function


    【解决方案1】:

    您可以使用以下声明:

    const double = (n: number) => n * 2;
    const map = <A, R>(f: (arg: A) => R) => (arr: A[]) => arr.map(f);
    const doubleArr = map(double); // (arr: number[]) => number[]
    
    console.log(doubleArr([1, 2, 3]));
    // ↳ [2, 4, 6]
    

    Playground sample


    解释:ARgeneric type parametersmap(double) 返回一个带有签名(arr: number[]) =&gt; number[] 的函数,因为TS 能够从double 分型中infer,所以AR 在这里都只能是number

    【讨论】:

    • 非常感谢!您能否指出文档中解释&lt;A, R&gt; 部分的正确部分?或者你可以修改你的答案来解释这里发生了什么?
    【解决方案2】:

    你可以声明一个接口然后传递它而不是Function

    interface ArrFunction<T> {
        (n: T): T
    }
    
    const double = (n: number) => n * 2;
    const map = (f: ArrFunction<any>) => (arr: Array<any>) => arr.map(f);
    

    【讨论】:

    • 现在可以编译,但它不能正确推断doubleArr 的类型。 const doubleArr: (arr: any[]) =&gt; any[]
    • 你可以通过下一步改进它,const map = &lt;T&gt;(f: ArrFunction&lt;T&gt;) =&gt; (arr: Array&lt;T&gt;) =&gt; arr.map(f);
    【解决方案3】:

    您可以使用两个参数创建一个函数map:数组和函数,以及何时要使用此函数,您应该将数组中的一个项目提供给此函数。

    const double = (n: number) => n * 2;
    const map = (arr: Array<any>, f: Function) => arr.map((item: any) => f(item));
    map([1, 2, 3], double)
    

    【讨论】:

    • 嗨,卡米尔,感谢您的帮助。我一直在寻找 curried map
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-02
    • 1970-01-01
    • 2020-02-15
    • 2018-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多