在打字稿中,如果启用了严格的null检查,我希望编译器可以防止我将null
或undefined
值分配给变量,除非它允许null
。
但是,数组访问似乎允许绕过此支票。
示例:
let a: string[] = ["Hello"];
let s: string;
// 1) this produces an error, as expected
s = undefined
// 2) s is undefined here, too, but no error
s = a[3];
console.log(s);
打字稿操场上的可运行版本(请注意:"严格的null检查"必须在"选项"对话框中启用)。
这里发生了什么?
- 这是打字稿编译器中的错误吗?
- 还是故意的遗漏?
- 如果后者是任何地方记录的(理想情况下,为什么要这样做)?
找到了它: - )。
tl; dr:这是故意的遗漏。在打字稿代码中,数组访问非常常见,并且强迫每次访问的空/未定义检查对于开发人员来说太麻烦了。
请注意,由于Typescript 4.1这是可以使用编译器选项noUncheckedIndexedAccess
配置的。有关详细信息,请参见Klaster_1的答案。
该问题在讨论中已多次提出:
- 问题#11122-数组查找应返回t |未定义
- 对PR 7140的评论
- #6229-建议:严格和开放的元组类型
对PR 7140的评论有Anders Hejlsberg(核心开发人员之一)的不错的理由:
索引简单地产生匹配中声明的类型的值索引签名。即使在技术上更正确,它也会如果我们自动将
undefined
添加到类型每个索引操作。例如,每个数组元素访问必须伴随着非无效的后卫或
!
断言。我认为这会变得非常烦人。
个人评论:我认为这是一个合理的决定。问题是数组固有的 - 我认为是否可以(对于编译器)证明是否定义给定位置,因为您可以使用计算的位置。因此,任何警告都会产生许多误报,大多数开发人员无论如何都会关闭它。
本质上,阵列为开发人员提供了比编译器可以检查的更多自由。如果您需要进行适当的检查,我可以看到的唯一解决方案是避免直接访问阵列,并使用其他提供更多保护的数据结构。
typescript 4.1引入了一个新的编译器选项-NOUNCHECKECKEDINDEXEDACCESS。除其他外,它将undefined
添加到数组索引访问类型。
考虑以下片段(TS游乐场):
const items = [1,2,3]
console.log(items[1]?.toString(10))
console.log(items[2].toString(10))
没有noUncheckedIndexedAccess
,items[2].toString(10)
将被视为有效,并且在选项打开时无效。该选项打开时,items[1]?.toString(10)
将有效,就像Alex Neth在旧答案中的评论一样。