以下代码
let k = "1";
k += 1;
console.log(k);
即使在严格模式下,也可以使用TypeScript正确编译。我本来希望tsc失败并出现诸如Cannot add a string and an integer.
之类的错误。为什么建立成功?我可以防止这种危险行为吗?
答案 0 :(得分:4)
“为什么有效,因为它在JS中是有效的”,对于某个操作不是类型错误的原因,这不是一个答案。参见What does "all legal JavaScript is legal TypeScript" mean?
在JavaScript中,像alert("Your position in the queue is " + queuePos)
这样的代码是惯用且通用的-通常不是写为"str" + num.toString()
的。
TypeScript的立场是,惯用JS不应引起类型错误(在可行时)。这意味着string + number
是允许的强制。
然后+=
应该做什么的问题是在两个选项之间进行选择:
x = x + y
应该与x += y
相同x += y
和string
操作数之间通常不执行number
,因此应强制执行非法操作这两种选择都是明智和辩护的; TypeScript恰好选择了第一个。
答案 1 :(得分:2)
恐怕除了建立自己的抽象外,目前无法阻止这种转换。这样的东西(诚然,不是很优雅):
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'.
根据"All legal JavaScript is legal TypeScript",TypeScript的类型检查的通常策略是防止出现明显错误且实际上没有用的情况。例如,防止将字符串传递到Math.max
。但是,与本示例不同,尽管并不总是希望在字符串和数字之间使用+
运算符,但它确实是有效的操作,并且在实践中经常使用,以致于编译器无法使用。由于x += y
等效于x = x + y
,并且在x
是字符串时总是产生一个字符串,因此赋值本身也是有效的。这是编译器最有可能保持正常状态的情况之一。问题#20131的目的是使其他一些操作发出警告,但特别是不包括此警告。
您可能已经了解到,成功地防止了相反的情况,因为预计变量不会使用添加分配运算符更改其类型。
let y = 1;
y += "1"; // Type 'string' is not assignable to type 'number'
另请参阅:
答案 2 :(得分:0)
简而言之:因为@Explosion Pills已经指出,它是有效的JS和Typescript。
原因是k += 1
只是k = k + 1
的语法糖,人们期望它是 11 。
所以类似的事情也可以:
let text = "hello ";
text += "world!"
console.log(text);
最终成为你好世界!
答案 3 :(得分:0)
您可以使用tslint规则restrict-plus-operands来预防此类事故:
添加两个变量时,操作数必须均为数字类型或字符串类型。
配置示例:
WHERE MATCH(dbase-field) AGAINST('$querystring' IN NATURAL LANGUAGE MODE) AND if (there is any text in dbase-field2) { MATCH(dbase-field2) AGAINST('$querystring' IN NATURAL LANGUAGE MODE) }
如果启用该规则,则以下代码:
"restrict-plus-operands": true
将导致:
错误:.ts-'+'操作的操作数必须是两个字符串或两个数字,但找到5 +“ foo”。考虑使用模板文字。
该规则不仅禁止在字符串和数字之间使用const x = 5;
const y = 'foo';
const z = x + y;
console.log(z);
,而且还禁止在左侧类型与右侧类型不同时使用+
。
答案 4 :(得分:0)
TSLint建议使用模板文字而不是强制使用字符串和数字变量,
例如:'Hello ' + person.name
将变成`Hello ${person.name}`