【问题标题】:Typescript "Object is possibly 'null'" false alarm打字稿“对象可能是'null'”误报
【发布时间】:2020-03-25 23:35:00
【问题描述】:

我有以下代码:

isEmpty(vehicle: VehicleTitle) {
    return this.options && this.options[vehicle.type] && this.options[vehicle.type].length === 0;
}

IDE (VSCode) 指向this.options[vehicle.type].length 并说

对象可能是“空”

你不认为这是一场虚惊吗?这里有什么问题?

编辑

最小的可重现示例here

【问题讨论】:

  • 您是否误读了错误?因为如果isEmpty 应该返回一个布尔值,那么它可以在它之前短路的情况下也返回null。而且 null 与布尔值不同。这可能是这里的错误,但我只是猜测。
  • 不,错误正是我所说的。此外,isEmpty 的返回类型不正确是对的。
  • 嗯,我可以重新创建它if I do this。但我不确定这是不是你的情况。
  • 车辆可能为空

标签: typescript


【解决方案1】:

这似乎是 TypeScript 中的一个错误!

Here is a previous bug along these lines 该错误已在 2019 年 7 月修复,但受影响的行为是:

const obj: { [key: string]: any[] | null }  = { prop: [] };

obj["prop"] && obj["prop"].length; //error
obj.prop && obj.prop.length; //OK

从 3.6.0 版开始,情况不再如此,两行都被接受。似乎现在有一个稍微不同的问题,但大纲是一样的:

const obj: { [key: string]: any[] | null }  = { prop: [] };

const key = "prop" as const;
obj[key] && obj[key].length; //error
obj.prop && obj.prop.length; //OK

当使用任何变量(甚至是常量)进行属性访问时,TypeScript 会报告与以前相同的错误。

有一个similar older bug 与括号表示法有关,一般不被视为与点表示法相同。那个已于 2018 年 8 月关闭,但已在 12 天前(2020 年比赛)重新开放。看起来团队已经意识到了这个问题,并正在重新审视后一个问题以进行修复。

同时,这里有几个方法可以避免编译错误:

使用非空断言

您可以简单地使用后缀! 运算符执行non-null assertion,您将解决问题:

isEmpty(vehicle: VehicleTitle) {
  return this.options && this.options[vehicle.type] && this.options[vehicle.type]!.length === 0;
//                                                                               ^
}

Playground Link

使用中间变量进行检查

如果你想避免断言,你可以只取值然后使用它。这将确保编译器您实际上并没有获取两个不同的值:

isEmpty(vehicle: VehicleTitle) {
  const value = this.options && this.options[vehicle.type];
  return value && value.length === 0;
}

Playground Link

使用可选链

Typescript 还有一个功能可以为您做同样的检查,称为optional chaining。它是每个可能不存在的属性之后的后缀?

isEmpty(vehicle: VehicleTitle) {
  return this.options?.[vehicle.type]?.length === 0;
//                   ^               ^
}

Playground Link

【讨论】:

  • 你不能对新添加的代码行说同样的话吗? typescriptlang.org/play/#code/…
  • @Ahmad 好的......好吧,我想编译器会以不同的方式处理括号访问。如果是这样,它不起作用的原因就更加愚蠢了——它假设vehicle.type 可以在两个调用之间更改,而不是检索到的对象。就像我在答案中展示的那样,使用吸气剂在技术上仍然是可行的,但我认为这比以前更没有意义。
  • @Ahmad 好的,所以,这甚至不是vehicle.type 的问题。 I changed it to a constant 它还在抱怨。我很困惑。我会努力寻找更多。
  • @Ahmad 好的,找到原因了。现在它是有道理的,为什么它没有意义 - it's a bug...我会根据这个修改我的答案。
  • @Ahmad 等等……我现在更加困惑了。该问题已关闭并且显然已修复。我尝试了错误线程中的重现代码,它不再引发错误。但是,如果您使用变量而不是常量,它确实 - 您正在经历什么。所以,obj["prop"] && obj["prop"].length - 好的,obj.prop && obj.prop.length - 好的,但是 const p = "prop"; obj[p] && obj[p].length - 错误。即使设置 const p = "prop" as const 也不会改变这一点。真的很奇怪。我认为这里仍然存在错误,我将不得不进一步研究它。
猜你喜欢
  • 2020-04-25
  • 2017-10-12
  • 2021-08-09
  • 1970-01-01
  • 2020-11-07
  • 2019-07-30
  • 2022-01-26
  • 1970-01-01
  • 2021-12-01
相关资源
最近更新 更多