具有严格空值检查的TypeScript-数组访问如何?

sle*_*ske 3 null types typescript2.0 strictnullchecks

在TypeScript中,如果启用了严格的null检查,我希望编译器阻止我向变量赋值nullundefined值,除非它允许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);
Run Code Online (Sandbox Code Playgroud)

TypeScript Playground上的可运行版本(注意:必须在“选项”对话框中启用“严格的空检查”)。

这里发生了什么?

  • 这是TypeScript编译器中的错误吗?
  • 还是故意遗漏?
  • 如果是后者,此文件是否记录在任何地方(理想的理由是这样做的理由)?

Kla*_*r_1 8

TypeScript 4.1 引入了一个新的编译器选项 - noUncheckedIndexedAccess。除此之外,它还添加了undefined数组索引访问类型。

考虑以下代码片段(TS Playground):

const items = [1,2,3]
console.log(items[1]?.toString(10))
console.log(items[2].toString(10))
Run Code Online (Sandbox Code Playgroud)

不带noUncheckedIndexedAccess,items[2].toString(10)则视为有效,勾选时视为无效。items[1]?.toString(10)当该选项打开时,该选项将有效,就像 Alex Neth 在旧答案中的评论一样。


sle*_*ske 5

找到了 :-)。

tl; dr:这是故意遗漏的。数组访问在TypeScript代码中非常常见,因此对开发人员来说,对每次访问强制执行null / undefined检查都非常麻烦。


在讨论中已多次提出该问题:

PR 7140的评论来自Anders Hejlsberg(核心开发人员之一)的一个很好的理由:

索引只是产生匹配索引签名中声明的类型的值。即使从技术上讲它是正确的,但如果我们自动将其添加undefined到每个索引操作的类型中,也将非常痛苦。

例如,每个数组元素访问都必须伴随一个非空的保护或一个!断言。我认为那将变得非常令人讨厌。

  • 非常不幸 (2认同)
  • 对于语言而言,这确实是一个糟糕的决定。Typescript 中有很多令人非常恼火的事情 - 这是有充分理由的!任何一天我都会把安全和恼人的事情放在不安全的事情上。 (2认同)
  • 我觉得 foo?[0] 在用户想要指示编译器不应该尝试的地方会很好。或者至少应该有一个经过严格检查的打字稿类型的数组。 (2认同)