【问题标题】:Typescript > Generics > Union Constraint打字稿>泛型>联合约束
【发布时间】:2019-09-23 00:43:33
【问题描述】:

为什么打字稿编译器会抛出以下错误:

Operator '+' cannot be applied to types 'T' and 'T'.,

编译时:

export const addNumbersOrCombineStrings = <T extends string | number>(
  param1: T,
  param2: T
): T => param1 + param2

?

【问题讨论】:

    标签: typescript typescript-generics


    【解决方案1】:

    GitHub 中的相关问题是Microsoft/TypeScript#12410commentRyan Cavanaugh 解决了您的特定问题:

    T + T where T extends string | number 仍然是不允许的——我们认为这不是一个好的用例,因为你是否得到连接或加法是不可预测的,因此人们不应该做的事情.

    如果您只是尝试将两个 string | number 类型相加,也会发生同样的事情:

    declare const x: string | number;
    x + x; // error!
    // Operator '+' cannot be applied to types 'string | number' and 'string | number'.
    

    所以我猜他们是认真的,他们不想让你这样做。您始终可以根据自己的意愿弯曲编译器并使用 type assertion 禁用类型检查;

    export const addNumbersOrCombineStrings = <T extends string | number>(
      param1: T,
      param2: T
    ): T => (param1 as any) + param2;
    

    但你不想这样做,尤其是因为 T extends string | numberinfer 一个 stringnumber 文字,这不会给你你期望的行为:

    const notThree = addNumbersOrCombineStrings(1, 2);
    // const notThree: 1 | 2
    
    const notHi = addNumbersOrCombineStrings("h", "i");
    // const notHi: "h" | "i"
    

    糟糕,这些结果是文字的联合。要使用泛型解决这个问题,您可能需要开始使用花哨的conditional types 来扩大文字范围:

    type SN<T extends string | number> = (T extends string ? string : never) | 
      (T extends number ? number : never);
    
    export const addNumbersOrCombineStrings = <T extends string | number>(
      param1: T,
      param2: SN<T>
    ): SN<T> =>
      (param1 as any) + param2;
    
    const n = addNumbersOrCombineStrings(1, 2); // const n : number;
    const s = addNumbersOrCombineStrings("h","i"); // const s: string;
    
    // and do you even want to support this:
    const sn = addNumbersOrCombineStrings(
      Math.random() < 0.5 ? "a" : 1,
      Math.random() < 0.5 ? "b" : 2
    ); // const sn: string | number;
    

    但也可能存在边缘情况(比如传入的值实际上是string | number,就像上面的sn 情况一样)。我开始明白为什么他们不想支持将string | number 类型的值一起添加。无论如何,希望这会有所帮助。祝你好运!

    【讨论】:

      猜你喜欢
      • 2021-10-04
      • 2021-04-20
      • 1970-01-01
      • 2022-11-23
      • 1970-01-01
      • 2016-11-13
      • 2020-08-03
      • 1970-01-01
      • 2021-07-24
      相关资源
      最近更新 更多