类型缩小:当 noUncheckedIndexedAccess 为真时检查变量对象键是否存在

Type narrowing: checking variable object key existence when noUncheckedIndexedAccess is true

我的 tsconfig.json 中有 "noUncheckedIndexedAccess": true。开关的全部要点是在访问索引之前强制检查该项目是否存在。

我很难用可变键检查对象:

假设我有以下结构:

const items: Record<string, {name: string}> = {
  '123': {
    name: 'asdf'
  }
}

当我尝试使用文字键检查是否存在时,类型缩小工作正常:

if (items['123']) {
  // OK: Compiles no problem
  console.log(items['123'].name)
}

如果我尝试使用可变键检查是否存在,编译器就会开始报错。

const id = '123';
if (items[id]) {
  // ERROR: items[id] - Object possibly undefined
  console.log(items[id].name)
}

为什么不能那样检查是否存在?

我什至尝试了不同的检查:

if (id in items) {}
if (items.hasOwnProperty(id)) {}
if (typeof items[id] !== 'undefined') {}

运气不好。

唯一有效的是

const id = '123';
const item = items[id];
if (item) {
  // OK
  console.log(item.name)
}

不过我觉得有点太啰嗦了。

▶️ Examples above in TypeScript Playground

环境: TypeScript v4.5.4

GitHub 上有一个问题基本上描述了这种确切情况:

Can't narrow T | undefined into T with a falsy check when using --noUncheckedIndexedAccess

该问题作为此问题的副本已关闭,该问题截至 2022 年 2 月仍未解决:

Discriminant property type guard not applied with bracket notation

根据对第二个问题和其他相关问题的讨论,这听起来像是一个已知的限制,因为在类型检查器中实现它需要性能开销,例如here:

Declined due to performance reasons. Since it should almost always be possible to write const j = list[i] instead, this shouldn't be too burdensome.

鉴于问题仍未解决,这似乎有可能 re-addressed 在某些时候支持您期望的行为。