【问题标题】:How does one type this default value in TypeScript?如何在 TypeScript 中键入此默认值?
【发布时间】:2021-11-04 12:38:38
【问题描述】:

抱歉标题模糊,但我不知道如何简洁地表达这个问题。

基本上,我有以下代码(删除了不重要的部分):

function identity<T>(value: T): T {
    return value;
}

function extent<T, K>(
    values: T[],
    map: (value: T) => K = identity // the '= identity' part gives an error
): [K, K] | undefined {
    let min;
    let max;

    // ... stuff ...

    return min === undefined || max === undefined ? undefined : [map(min), map(max)];
}

默认= identity 值会导致编译器错误。

我可以从extent 的签名中删除map 参数的默认值,并始终自己提供一个:

extent([5, 1, 3, 4, 8], x => x)

这可以正常工作,但我宁愿不提供第二个参数,除非我实际上将值从一种类型映射到另一种类型。

如何键入indentity 函数,以便将其作为extentmap 参数的默认值接受?如果这很重要的话,我暂时停留在 TypeScript 3.6 上。

【问题讨论】:

    标签: typescript generics default-value return-type typing


    【解决方案1】:

    处理这个问题的最好的方法可能是保持对外界的类型安全是通过重载:

    function extent<T>(values: T[]): [T, T] | undefined
    function extent<T, K>(values: T[], map: (value: T) => K): [K, K] | undefined
    function extent<T, K>(
      values: T[],
      map?: (value: T) => K 
    ): [K, K] | [T, T] | undefined {
      const actualMap = map ?? identity;
      let min;
      let max;
    
      // ... stuff ...
    
      return min === undefined || 
             max === undefined ? 
                 undefined : 
                 [actualMap(min), actualMap(max)];
    }
    

    【讨论】:

    • 太棒了!这就是我一直在寻找的不妥协的解决方案!谢谢?
    • 实际上,如果我声明 min/max 的类型,它仍然会失败:let min: T; let max: T; 我的意思是,在我的代码中我不必声明它,因为它是编译器从代码中推断出来的我省略的部分(标记为“......东西......”),但它仍然失败。所以extent的返回类型应该不是[K, K] | [T, T] | undefined而是[T | K, T | K] | undefined,但是这个方案还是有效的??
    • @Vitaly 在我自己的一些项目中,我有相同的 identity 函数和相同的签名,并且花了很短的时间才得到这个干净(或者至少对任何消费者来说都是干净的!) .很高兴能提供帮助。
    【解决方案2】:

    这是因为类型错误。

    map 参数中,您声明此函数将返回K 的类型,但在identity 函数中,您希望返回T 的类型,因此您不能将其分配为默认值.

    你可以这样修复它:map: (value: K) =&gt; K = identity

    【讨论】:

    • 如果映射到 K 以外的其他东西,那将没有多大用处。
    • 是的,我只是在作者的情况下快速回答。
    【解决方案3】:

    T =&gt; K 类型的 map 和 K =&gt; K 类型的标识函数有冲突。让 identity 对类型不那么严格会有所帮助:

    function identity<T>(value: T): any {
        return value;
    }
    

    甚至

    const identity = (x: any) => x;
    

    【讨论】:

    • 是的,但是编译器将无法正确推断 extent 函数的返回类型。可以是[unknown, unknown][any, any]
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-28
    • 2016-05-06
    • 2022-11-15
    • 2018-10-14
    • 2021-05-30
    • 2019-05-02
    • 2019-12-02
    相关资源
    最近更新 更多