typescript - 为什么在 strictNullChecks 开启时 null 变量仍会扩大以键入任何内容?
问题描述
TypeScript DocsstrictNullChecks
说如果是真的,它不应该再扩大类型。并且 typeofnul
应该是null
.
let nul = null; // typeof nul = any
let undef = undefined; // typeof undef = any
strictNullChecks
在 TSConfig 选项卡中打开Playground。nul
和的类型undef
仍然是any。为什么?</p>
更新:
谢谢@jcalz。我发现了一些有趣的东西:
// strictNullChecks=true;
let z = null; // hover on z, quick info shows: let z: any <--
type A = typeof z; // type A = null
// strictNullChecks=false;
let z = null; // hover on z, quick info shows: let z: any
type A = typeof z; // type A = any <---
解决方案
当 TypeScript 2.0 发布时,您链接的文档可能是准确的。但是当 TypeScript 2.1 发布时,它引入了改进的any
推理,在microsoft/TypeScript#11263中实现。
从那时起,如果您启用--noImplicitAny
,当您将非const
变量初始化为null
or undefined
(或根本不初始化它)时,编译器将其类型推断为any
而不是null
or undefined
,即使--strictNullChecks
启用,甚至对于 TypeScript 代码(如反对检查 JavaScript 代码):
let nLet = null; // any
let uLet = undefined; // any
var nVar = null; // any
var uVar = undefined; // any
const nConst = null; // null
const uConst = undefined; // undefined
动机似乎是,当您使用null
or初始化变量时undefined
,您很可能稍后将其更改为其他内容,并且该any
类型允许控制流分析进行后续缩小:
let x = undefined;
while (!x) {
if (Math.random() < 0.5) x = "finished";
}
x // string
x.toUpperCase(); // okay
x.toFixed(); // error
在这里,编译器允许分配 a string
to x
(如果x
是 type则禁止),并且一旦你退出循环,它undefined
也会看到它x
是 type的,所以它让你把它当作 a而不是其他任何东西(例如一)。string
string
number
即使在初始分配时,控制流分析也会将这些变量的表观类型缩小到null
并且undefined
如果您只是将变量注释为 type 则不会发生这种情况any
:
let nLet = null; // any
nLet.x // error, Object is possibly 'null'
let uLet = undefined; // any
uLet.x // error, Object is possibly 'undefined'
let aLet: any;
aLet.x // no error
null
因此,在实践中,您可能不会观察到变量初始化为or的太多问题undefined
。
推荐阅读
- swift - “致命错误:索引超出范围 2019-08-30 11:01:35.001667-0400 fmcBeta[58563:3478851] 致命错误:索引超出范围”
- python - 将列合并为一列,由一个字符分隔适用于所有行
- json - 如何将\u0421转换为字母“C”?
- python - WSGI & Python 子进程
- c++ - 如何处理 SDL 中的输入?
- jenkins - sh'''有什么用
''' - 三个滴答声 - 在 Jenkinsfile 中? - excel - 在所有工作表中,双击颜色单元格
- .htaccess - 如果请求 php 文件,一个简单的 .htaccess 重写规则无法按预期工作
- reactjs - ReactJS 错误:超过最大更新深度
- node.js - 使用 express 验证器作为中间件验证密码