首页 > 解决方案 > forEach 循环中设置的变量类型错误

问题描述

forEach回调函数内部设置变量时,该变量的类型似乎不正确。一个简单的例子:

let foo: (string | null) = null;

[1,2,3].forEach((i) => {
  foo = "bar";
});

if(foo == null) {
    throw new Error("not found")
}

# Typescript complains that `length` is not a property of type `never`
console.log(foo.length)

打字稿游乐场链接

forEach我期望的类型foo是之后string | null,但它实际上只是null。顺便说一句,console.log我希望它只是string,但实际上是never(因为我们已经消除nullError投掷的可能性。

重要的是,上面的代码(减去: (string | null)一点)在纯 JavaScript 中工作得非常好——这纯粹是我和 TypeScript 编译器无法以某种方式正确通信的情况。

所以无论如何:

  1. 如果有人能解释为什么会这样,我会很高兴,这样我就可以更好地理解 Typescript 并且
  2. 我该如何解决这个问题?我可以foo = foo as string在 console.log 之前拍一下,但肯定有更好的方法吗?

标签: typescriptcontrol-flowtype-narrowing

解决方案


这是控制流分析的权衡之一。

通过注释类型string | null,您告诉编译器该变量显然需要任一类型的值。然后对 进行赋值null,让编译器将类型缩小到null

您希望 TypeScript 考虑回调内部的分配并放弃缩小范围,但事实并非如此。这是团队在决定作为参数传递给高阶函数的函数中发生的突变是否应该泄漏到外部范围时做出的权衡。

请参阅有关此问题的源代码库讨论。


推荐阅读