尽管“unknown”有官方语义,“unknown”类型被强制为“string”

问题描述

我已经阅读了关于未知类型的官方文档,但我很难真正理解它是如何工作的。

人们可以在文档中读到:“在不首先断言或缩小到更具体的类型之前,不允许对未知进行任何操作。”

但是如果我有这个功能

const foo = (x: unkNown) => {
  return x + "3";
}

TypeScript 没问题,但是这个函数会引发一个错误,告诉 x 未知:

const foo = (x: unkNown) => {
  return x + 3;
}

为什么它与 x + "3" 一起使用?

如果涉及强制转换,例如 true + 3 或 {} + 3 以及 true + "3" 也可以。

解决方法

这是因为 Typescript 的设计者选择允许 unchecked Javascript 的许多隐式强制转换,通常是因为它们太惯用了。

Suggestion: stricter operators #7989

目前,像“+”这样的运算符被定义为与它们在 JS 中的语义相匹配。编译器允许以下所有内容并生成显示的值,即使 --strictNullChecks 打开。

  • 2 + 'a' => "2a"
  • null + 'a' => "nulla" (!)
  • 2 - null => 2

Typescript 维护者一直保持这个问题处于开放状态,表明他们愿意改变这一点,或者至少添加一个新的编译器严格标志。

项目负责人 Ryan Cavanaugh 说:

已批准的行为更改:在 --strictNullChecks 下,在 +-/、{ 中使用可能为空/可能未定义的操作数应该是错误的{1}}、*|&^ 表达式。一个例外是 ** 仍然可以,因为这对于生成调试字符串非常常见。

,

在对 + 二进制表达式进行类型检查时,如果至少一个操作数是字符串(在本例中为 "3"),则编译器会将整个表达式推断为字符串。

摘自checkBinaryLikeExpressionWorker (https://github.com/microsoft/TypeScript/blob/main/src/compiler/checker.ts#L32087) 中的评论

如果两个操作数都是 Number 原始类型,则结果为 Number 原始类型。
如果一个或两个操作数是 String 原始类型,则结果 是 String 原始类型。

x + 3的情况下,“数字”测试失败,最后输入表达式any并报告错误。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...