为什么 TS 在一元算术运算中不安全,而在二进制运算中不安全?



在算术中,以下内容是正确的:设'a'是任何正实数,因此:

-a = a*(-1)  

Typescript 编译器似乎没有以类型安全的方式重现算术规则。看:

(一(按预期工作

以下行生成此错误消息:">算术运算的左侧必须是类型'any'、'number'、'big-int'或枚举类型">

const f = (a: string) => a*(-1)  // error
const g = (a: {}) => a*(-1)      // error

(二(工作不按预期

在下面的场景中,所有算术计算都使用非数值类型不安全地执行,并且不会引发编译时错误。


const f = (a: string) => -a
const g = (a: {}) => -a 
console.log(f('hi there')) // produces 'NaN' !
console.log(g('hi there')) // produces 'NaN'
console.log(g(2)) // produces -2

问题

  • 为什么 TS 在一元运算符中不如在二进制运算符中安全?

注意:TS 版本 3.7.2/类型"未知"按预期工作

ECMAScript 规范指出,一元+和一元-运算符都对其输入表达式执行抽象操作ToNumber()

12.5.6 一元 + 运算符

注意 一元 + 运算符将其操作数转换为数字类型*。

12.5.6.1 运行时语义:评估

一元表达式 : + 一元表达式

  1. 让 expr 是计算 UnaryExpression 的结果。

  2. 返回?ToNumber(?GetValue(expr((。

12.5.7 一元 - 运算符

注意 一元运算符将其操作数转换为数字类型*,然后对其进行求反。否定 +0 产生 -0,否定 -0 产生 +0。

12.5.7.1 运行时语义:评估

一元表达式 : - 一元表达式

  1. 让 expr 是计算 UnaryExpression 的结果。

  2. 让旧值是 ?ToNumber(?GetValue(expr((。

  3. 如果 oldValue 为 NaN,则返回 NaN。

  4. 返回否定 oldValue 的结果;即计算一个大小相同但符号相反的数字。

*强调添加

TypeScript 没有理由对接受的类型施加任意限制,因为根据规范,主要预期用途是执行类型转换


回应伊曼纽尔·温蒂勒对上述问题的评论:

二元运算符还执行类型转换

规范不使用相同的语言,即

[...] 将其操作数转换为数字类型

在 乘法表达式 下;也就是说,虽然乘法*/%运算符确实执行类型转换,但它不是它们的主要预期用法。

最新更新