来晚了,但这是我的两分钱。
对被接受的答案的评论
if (a) {
a.toFixed();
}
请注意,当 a
的值为 0
时,if 代码块不会被调用。
- 要解决这个问题,请使用
if (a !== undefined)
- 否则(当您真的不想处理
0
时),最好将 a
初始化为 0
,例如:
let a = 0; // typescript will infer the type number
...
if (a) {
// a is of type number and !== 0
}
回复评论
为什么要使用 undefined 来初始化变量?
有些人这样做是因为一些工具(如IDE、linters等)否则会报告错误/警告。
例如,当您使用默认的TypeScript设置在IntelliJ IDEA中操作时,就会出现该警告:
我建议关闭这些检查,因为在 JavaScript 中未初始化的变量总是具有值 undefined
。换句话说,在其他某些语言(如 C 语言)中,变量可能具有某些随机的“垃圾”值。
来自 MDN: Global_Objects/undefined#description 的引用
未被赋值的变量的类型为 undefined。
对于所有其他值(即不是undefined
的值),TypeScript 编译器都会显示一个错误:
TS2454:变量 'xxx' 在赋值之前被使用。
回答原问题
let a: number | null = null;
[1].forEach(() => {
a = 1;
});
if (a != null)
a.toFixed();
只有在编译器选项
strictNullChecks
开启时才会发生此问题。
这段引用描述了原因(
引用来源):
“虽然
strictNullChecks
意味着仅检查变量的使用是否为 undefined 或 null,但实际上它将编译器置于非常悲观的模式下,当没有上下文推断类型的方式时,它将选择最狭窄的类型而不是最宽泛的类型。”
具体来说,这意味着:
- 由于 TypeScript 编译器不够聪明,无法知道 forEach 循环何时被调用(从而分配值),它采取悲观的方法,并假定
x
仍为
null
- 因此,循环后
x
的类型为
null
(不是我们可能期望的
number | null
类型)
- 现在,最终的 if 块检查
x !=== null
,这永远不可能发生(因为 TypeScript 假设 x 在执行 if 语句时
是 null
)。 因此,在 if 语句内部,
x
的类型为
never
- 因此,“解决方案”之一是使用
x!.toFixed()
明确告诉 TypeScript,您确定
x
的值已定义。
其他:
Misc
strictNullChecks
当关闭
strictNullChecks
时,代码可正常工作:
TypeScript 示例:strictNullChecks=off
我强烈不建议这样做。
for..of 循环
当你使用for..of循环而不是forEach()
时,即使开启了strictNullChecks
,代码也可以正常工作:Playground
let a: number | null = null;
for (const i of [1]) {
a = 1;
};
if (a != null)
a.toFixed();
其他初始值
您还可以考虑其他初始化值(而不是undefined
或null
):演示区
let a = 0; // typescript will infer that a is of type number
[1].forEach(() => {
a = 1;
});
if (a >= 0)
a.toFixed();
let b = NaN; // typescript will infer that b is of type number
[1].forEach(() => {
a = 1;
});
if (!isNaN(b))
b.toFixed();
forEach
的功能。此外,请记住,forEach
可以被修改以执行不同的操作,因此训练TypeScript了解它是毫无意义的。 - Andrei Tătar