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

Fla*_*nte 6 compiler-construction math typescript

在算术中,以下是正确的:让 ' a ' 是任何正实数,所以:

-a = a*(-1)  
Run Code Online (Sandbox Code Playgroud)

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

(一)按预期工作

以下几行产生此错误消息:“算术运算的左侧必须是‘any’、‘number’、‘big-int’或枚举类型”

-a = a*(-1)  
Run Code Online (Sandbox Code Playgroud)

(二)没有按预期工作

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

const f = (a: string) => a*(-1)  // error
const g = (a: {}) => a*(-1)      // error
Run Code Online (Sandbox Code Playgroud)

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

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

Pat*_*rts 5

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. 让 oldValue 是?ToNumber (? GetValue (expr))。

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

  4. 返回对 oldValue 取反的结果;也就是说,计算一个大小相同但符号相反的数字。

*强调添加

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


Emanuel Vintil?对上述问题的评论

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

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

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

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