🔎 搜索词
常量索引访问,数组
🕗 版本与回归信息
- 在版本
5.4.5
和5.5.beta
之间发生了变化 - 在提交或 PR 中发生了变化
⏯ Playground链接
- 由于库导入,我无法在Playground中复现此问题*
💻 代码
import crypto from 'crypto-js'
const bar = "abc"
const foo: crypto.lib.WordArray = crypto.enc.Utf8.parse(bar) // Returns type: { words: number[], ... }
for (let i = 0; i < foo.words.length; i++) {
foo.words[i] += 1
//~~~~~~~~~~~~ error TS2532: Object is possibly 'undefined'.
// Alternatively:
foo.words[i] = foo.words[i] + 1
// ~~~~~~~~~~~~ <same error>
}
在循环体内为假值添加适当的检查并不能解决问题,例如:
if (foo && foo.words && foo.words[i]) {
// Same code as above, same error
}
然而以下方法可以解决问题:
const word = foo.words[i]
if (word) {
foo.words[i] = word + 1 // OK
}
🙁 实际行为
错误 TS2532:对象可能是“未定义”。
🙂 预期行为
没有错误 - 之前类型检查是正常的
关于此问题的其他信息
自从新的 Control Flow Narrowing for Constant Indexed Accesses
功能推出以来,这个问题是新的。回退到之前的 TypeScript 版本可以解决这个问题
7条答案
按热度按时间ljsrvy3e1#
你可以在playground中经常导入npm包,这是没有问题的。它能够获取它们的类型。
我在这里没有看到任何错误,无论是TS playground的夜间版本:
foo.words
类型为number[]
,所以我不确定你的测试中是如何让undefined
进入这一切的。也许你正在使用noUncheckedIndexedAccess
?这确实会显示行为上的区别:
TS 5.4
TS nightly
这反过来看起来像是正确性上的改进。
z9gpfhce2#
如果这只是一个数组,我不明白为什么你需要
crypto-js
作为重现的一部分。请提供一个最小示例,带有配置,展示发生了什么qyyhg6bp3#
@RyanCavanaugh 是的,我知道这一点,但在没有这个包的情况下,我无法找到一个可复现的案例。
@Andarist 我认为你抓住了问题的关键-非常感谢,这肯定是问题所在。不确定这里的操作是什么,我会关闭这个问题,但请根据需要重新打开。
rsaldnfx4#
这里是在TS Playground(基于@Andarist的示例)中的最小复现:
包括代码以便于跟踪:
bweufnob5#
这里的问题是
i
被分配给了 so,因此无法通过这个检查:https://github.com/microsoft/TypeScript/pull/57847/files#diff-d9ab6589e714c71e657f601cf30ff51dfc607fc98419bf72e04f6b0fa92cc4b8R26613
i
在循环中是特殊的。我们知道它只在循环块之后被分配。因此,对于这种情况,也许可以进行一些额外的微调。mbjcgjjk6#
哦,这对重新赋值的变量是不起作用的:
看到错误出现在似乎与刚刚添加的行没有真正关联的前一行,这有点令人毛骨悚然。
eagi6jfj7#
Possibly related
#59185