英文:
Why does TypeScript give me an 'Object is possibly undefined' error when using array.at(-1)?
问题
Typescript错误 "对象可能为'undefined'" 发生在我使用以下代码时:
array.at(-1).key //array[array.length - 1].key
例如,下面的代码不会出现错误:
class P {
public x: number
public constructor(x: number) {
this.x = x
}
}
const a = [new P(1)]
console.log(a[a.length - 1].x)
然而,下面的代码会出现错误:
class P {
public x: number
public constructor(x: number) {
this.x = x
}
}
const a = [new P(1)]
console.log(a.at(-1).x)
当我检查值是否为undefined时,也会出现这个错误:
class P {
public x: number
public constructor(x: number) {
this.x = x
}
}
const a = [new P(1)]
if (a.at(-1) !== undefined) console.log(a.at(-1).x)
英文:
Typescript error "Object is possibly 'undefined'." occurs when I use
array.at(-1).key //array[array.length - 1].key
For example, error does not occur with the code below
class P {
public x: number
public constructor(x: number) {
this.x = x
}
}
const a = [new P(1)]
console.log(a[a.length - 1].x)
However, error does occur with the code below
class P {
public x: number
public constructor(x: number) {
this.x = x
}
}
const a = [new P(1)]
console.log(a.at(-1).x)
It also occurs when I checked if the value is undefined.
class P {
public x: number
public constructor(x: number) {
this.x = x
}
}
const a = [new P(1)]
if (a.at(-1) !== undefined) console.log(a.at(-1).x)
答案1
得分: 4
数组索引的方括号运算符自 JavaScript 诞生以来就存在。长期以来,它是访问数组的唯一方式。是的,对于不存在的数组索引或对象键,它会返回 undefined
。但由于这个运算符在几乎所有代码中都广泛使用,并且检查索引结果是否为 undefined
会显得冗长和烦人,TypeScript 似乎决定破坏严格的声音性,并假装结果不是 undefined
。
Array.at()
是在 ES2022 中引入的前沿新方法。事实上,我看到当前的 TypeScript 编译器严格处理该方法的语义,并强制您检查结果是否为 undefined
。
至于为什么代码 if (a.at(-1) !== undefined) console.log(a.at(-1).x)
不起作用,这是因为一般情况下不能假定公共子表达式消除是有效的。该方法可能会被猴子补丁和/或具有副作用(包括修改数组本身)。使这段代码正确进行类型检查的方法是使用临时变量,这可以保证在检查和使用之间不会被修改,像这样:
const temp = a.at(-1);
if (temp !== undefined)
console.log(temp.x);
英文:
The square brackets operator for array indexing has existed since the birth of JavaScript. For the longest time, it was the only way to index into an array. Yes, it returns undefined
for array indexes or object keys that don't exist. But because of how pervasively this operator is used in essentially all code, and how verbose and annoying it would be to check if the indexing result is undefined
, it seems TypeScript decided to break strict soundness and pretend that the result isn't undefined
.
Array.at()
is a bleeding-edge new method introduced in ES2022. Indeed, I see that the current TypeScript compiler treats the method's semantics strictly and forces you to check if the result is undefined
.
As for why the code if (a.at(-1) !== undefined) console.log(a.at(-1).x)
doesn't work, it's because common subexpression elimination cannot be assumed to be valid in general. The method could be monkey-patched and/or have side effects (including modifying the array itself). The way to make that piece of code type-check properly is with a temporary variable, which guarantees that it won't be modified between the time of check and the time of use, like this:
const temp = a.at(-1);
if (temp !== undefined)
console.log(temp.x);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论