为什么 TypeScript 允许我添加一个字符串和一个数字?我可以预防吗?



以下代码

let k = "1";
k += 1;
console.log(k);

使用 TypeScript 正确编译,即使在严格模式下也是如此。我本来希望 tsc 会失败并出现一些错误,例如Cannot add a string and an integer..为什么它能成功构建?我可以防止这种危险行为吗?

"它是有效的,因为它在JS中是有效的"在为什么某个操作不是类型错误的上下文中是一个非答案;请参阅"所有合法的JavaScript都是合法的TypeScript"是什么意思?

在 JavaScript 中,像alert("Your position in the queue is " + queuePos)这样的代码是惯用的和常见的——它通常不写成"str" + num.toString()

TypeScript 的立场是惯用的 JS 不应该导致类型错误(如果可行(。这意味着string + number是允许的胁迫。

+=应该做什么的问题就是在两个选项之间进行选择:

  • 一致性x = x + y应与x += y相同
  • 安全性x += y通常不是stringnumber操作者之间进行的,因此应该是非法胁迫

这两种选择都是明智和可辩护的;TypeScript 碰巧选择了第一个。

您可以使用 TypeScript-ESLint 规则限制加操作数来防止此类事故:

添加两个变量时,操作数必须都是 number 或字符串类型。

配置示例:

"restrict-plus-operands": true

如果启用该规则,则以下代码:

const x = 5;
const y = 'foo';
const z = x + y;
console.log(z);

将导致:

错误:.ts - "+"操作的操作数必须是两个字符串或两个数字,但找到 5 + "foo"。请考虑使用模板文本。

该规则不仅防止在字符串和数字之间使用+,而且还防止在左侧类型与右侧类型不同时使用+=

恐怕除了构建自己的抽象之外,目前没有办法阻止这种转换。像这样的东西(诚然,不是很优雅(:

function safe_add(x: string, y: string): string { return x + y; }
let x = "1";
x = safe_add(z, 1); // Argument of type '1' is not assignable to parameter of type 'string'.

根据"所有合法的JavaScript都是合法的TypeScript",TypeScript的类型检查的通常策略是防止明显错误且从未真正有用的情况。例如,阻止将字符串传递给Math.max。然而,与此示例不同的是,字符串和数字之间的+运算符尽管并不总是可取的,但确实是一个有效的操作,并且在实践中使用得太频繁,以至于编译器禁止使用。由于x += y等价于x = x + y,并且当x是字符串时总是产生字符串,因此赋值本身也是有效的。这是编译器最有可能保持正常的情况之一。问题 #20131 旨在使更多操作引发警告,但不包括此操作。

您可能已经了解,可以成功防止相反的情况,因为变量不会使用 add-assignment 运算符更改其类型。

let y = 1;
y += "1"; // Type 'string' is not assignable to type 'number'

另请参阅:

  • "所有合法的JavaScript都是合法的TypeScript"是什么意思?
  • 隐式类型转换时出现 TypeScript 错误

简而言之:因为它是有效的JS和Typescript@Explosion正如Pills已经指出的那样。

原因是k += 1只是k = k + 1的句法糖,人们期望是11。 所以这样的东西也有效:

let text = "hello ";
text += "world!"
console.log(text); 

最终成为你好世界!

TSLint 建议使用模板文字而不是字符串和数字变量的强制, 例如:'Hello ' + person.name会变得`Hello ${person.name}`

相关内容

最新更新