TypeScript在使用array.at(-1)时为什么会出现’Object is possibly undefined’错误?

huangapple go评论65阅读模式
英文:

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);

huangapple
  • 本文由 发表于 2023年5月22日 13:02:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/76303154.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定