【问题标题】:How does Typescript "+" operator work with generics and functions?Typescript“+”运算符如何与泛型和函数一起使用?
【发布时间】:2019-08-28 06:35:14
【问题描述】:

我有一个函数,它接受一些值,并在其上执行 + 运算符和一个 2 值:

function myFunction(input: number): number {
    return input + 2;
}

如果我传递一个数字,它会将这个数字添加到2

const result = myFunction(2);
console.log('Result: ', result);
// Result: 2

如果我传递一个字符串,它会将这个字符串连接到2:

const result = myFunction(");
console.log('Result: ', result);
// Result: "22"

到目前为止一切都很好。现在我想使用泛型来捕获类型:

function myFunction<T>(input: T): T {
    return input + 2;
}

如果我想使用它来捕获参数的隐式类型,我可以这样做:

const result = myFunction(2);
console.log('Result: ', result);
// Error: `(parameter) input: T. Operator '+' cannot be applied to types 'T' and '2'.`

如您所见,TypeScript 返回有关类型和 + 运算符的错误,我不明白为什么。如果我明确设置类型,则相同:

const result = myFunction<number>(2);
console.log('Result: ', result);
// Error: `(parameter) input: T. Operator '+' cannot be applied to types 'T' and '2'.`

我不明白为什么它会返回 + 的错误。欢迎任何帮助!

【问题讨论】:

  • 也许在这里得到了回答:stackoverflow.com/questions/54470329/…
  • 还是不明白为什么myFunction&lt;number&gt;(2);不强制类型为return input + 2;;在这种情况下,TypeScript 不应该返回错误!

标签: typescript


【解决方案1】:

一般来说,TypeScript +operator 比 JavaScript +operator 更严格。后者可以进行类型之间的隐式转换,并且在操作数方面更宽容。

与泛型和函数的交互

让我们以你的函数为例。鉴于myFunction 位于下方,您会收到错误,因为T 可以是任何字面意思(有关兼容类型,请参阅下方的 TypeScript + 运算符部分)。

function myFunction<T>(input: T): T {
  // Operator '+' cannot be applied to types 'T' and '2'.  
  return input + 2; 
}

TypeScript 还要求您通过控制流分析缩小联合类型的范围,例如 string | number

declare const t: string | number;
t + 3; // Operator '+' cannot be applied to types 'string | number' and '3'.

// this works!
if (typeof t === "string") {
  const res = t + 3; // const res: string
} else {
  const res = t + 3; // const res: number
}

不幸的是,generics extending a union type 还不能很好地使用类型缩小:

function myFunction<T extends string | number>(input: T): string | number {
  if (typeof input === "string") {
    return input + 3;
  } else {
    // TypeScript could not narrow here to number, we have to cast.
    const inputNumber = input as number;
    return inputNumber + 3;
  }
}

我猜这将是最终版本并回答您的问题。作为增强,一个整洁的事情是实际返回一个条件类型。因此,当我们输入字符串时,我们想要返回字符串。类似物number -&gt; number。请参阅此 Playground 示例。


TypeScript +operator 的可能组合

操作数的类型矩阵(空格表示编译错误;例如在“Other”和“Boolean”类型之间):

+----------+---------+----------+---------+---------+--------+
|          |  Any    | Boolean  | Number  | String  | Other  |
+----------+---------+----------+---------+---------+--------+
| Any      | Any     | Any      | Any     | String  | Any    |
| Boolean  | Any     |          |         | String  |        |
| Number   | Any     |          | Number  | String  |        |
| String   | String  | String   | String  | String  | String |
| Other    | Any     |          |         | String  |        |
+----------+---------+----------+---------+---------+--------+

规范摘录:

二进制 + 运算符要求两个操作数都是 Number 原始类型或枚举类型,或者至少一个操作数是 Any 类型或 String 原始类型。枚举类型的操作数被视为具有基本类型 Number。如果一个操作数是空值或未定义值,则将其视为具有另一操作数的类型。如果两个操作数都是 Number 原始类型,则结果是 Number 原始类型。如果一个或两个操作数是 String 原始类型,则结果是 String 原始类型。否则,结果为 Any 类型。

有些短语似乎有点过时了。数字枚举解析为数字,但字符串枚举被视为字符串。使用nullundefined 和编号,无论是否设置严格,都会出现编译错误,使用字符串进行连接。 Playground


背景信息:Javascript +operator

加法运算符产生数字操作数或字符串连接的总和。

有些星座,你只能在 JavaScript 中“做”:

true + 1 // 2
false + false // 0
1 + undefined // NaN
1 + null // 1; typeof(1+ null) === "number";   // :)
new Date() + new Date() // toString() is invoked for both Date objects implicitly

Playground

希望,对于您的问题范围而言,这不是太多的文字!

干杯

【讨论】:

  • 现在我明白了,你的回答真的很有帮助。非常感谢!
猜你喜欢
  • 2014-08-06
  • 2017-12-28
  • 2017-01-11
  • 1970-01-01
  • 2011-09-29
  • 1970-01-01
  • 1970-01-01
  • 2019-10-02
  • 1970-01-01
相关资源
最近更新 更多