打字稿>泛型>联合约束

时间:2019-05-04 22:15:45

标签: typescript typescript-generics

打字稿编译器为什么会引发以下错误:

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

编译时:

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

1 个答案:

答案 0 :(得分:4)

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

  

T + TT扩展string | number的地方仍然被禁止-我们认为这不是一个好用例,因为无论是级联还是加法都是不可预测的,因此人们不应该这样做。

如果您尝试将两种string | number类型加在一起,也会发生同样的事情:

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

所以我想他们很认真,他们不希望您这样做。您始终可以随心所欲地编译编译器,并使用infer;

禁用类型检查。
export const addNumbersOrCombineStrings = <T extends string | number>(
  param1: T,
  param2: T
): T => (param1 as any) + param2;

但是您不想这样做,尤其是因为T extends string | numberstringnumberconditional types的文字,它不会给您预期的行为:

const notThree = addNumbersOrCombineStrings(1, 2);
// const notThree: 1 | 2

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

糟糕,这些结果是文字的并集。为了解决泛型问题,您可能要开始使用花式{{3}}来扩展字面量:

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类型的值加在一起。无论如何,希望能有所帮助。祝你好运!