【问题标题】:Inference problem: "...referenced directly or indirectly in its own initializer"推理问题:“......在其自己的初始化程序中直接或间接引用”
【发布时间】:2020-10-03 15:23:37
【问题描述】:

我将今天遇到的一个问题简化为这个最小的示例。 (playground link)

function test() {
    interface Foo<T> {
        type: 'Bar'
    }

    function nextFoo<T>(it: Foo<T>): Foo<T> {
        return it
    }

    let foo: Foo<string> | undefined = { type: 'Bar' }
    while (foo !== undefined) {
        // Type inference error here but TS has the correct inference when hovering over nextFoo
        const next = nextFoo(foo) 
        foo = next // commenting this out masks the issue
    }
}

这似乎是 TypeScript 应该能够处理的事情。当我在 vscode 中将鼠标悬停在 nextFoo 上时,它看起来确实可以正确推断出那里的类型。将foo 设置为next 而可能是undefined 会导致这种情况。

有人能解释一下这里发生了什么吗?

【问题讨论】:

  • 编译器看到next的类型取决于foo的类型,这显然取决于next的类型(因为将next分配给foo将重置任何控制-流量变窄)。 const next: Foo&lt;string&gt; = 的显式类型注释将修复它。我认为这与microsoft/TypeScript#1146 中的问题基本相同。
  • @jcalz 我不明白为什么foo 的类型推断取决于next。它已经明确设置正确了吗?我在任何地方(给人类)分配给 foo 的内容都没有关系,类型不会与我声明的类型不同。在能够通过从 foo 类型中删除 | undefined 来解决此问题的上下文中,我也无法理解该解释。这也解决了这个问题,而无需输入next,因此必须在某处发生其他事情。
  • 控制流分析发生在测试或分配联合类型的值时。所以foo = next,其中foo 的声明类型是联合类型,对foo 的表观类型有影响。这意味着编译器的类型推断依赖关系图将显示foo 的类型取决于next 的类型。显然,人类只能“看到”类型应该是什么,但编译器使用了一种明显检测循环性的特定算法。我应该把它写下来作为答案还是我还缺少什么?
  • @jcalz 是的,我认为这是一个很好的答案。我从中得到的是,在处理涉及联合类型的类型推断时,它是编译器实现的副作用。我不知道我是否应该将其视为错误。天真地,它似乎可以在具有指定类型的条件下被短路,或者只是通过在硬编码类型时不尝试通过图形推断类型而一起规避,就像 foo 分配的情况一样。跨度>

标签: typescript type-inference


【解决方案1】:

作为一种解决方法,您可以强烈键入 next 变量:

function test() {
    interface Foo<T> {
        type: 'Bar'
    }

    function nextFoo<T>(it: Foo<T>): Foo<T> {
        return it
    }

    let foo: Foo<string> | undefined = { type: 'Bar' }
    while (foo !== undefined) {
        // Type inference error here but TS has the correct inference when hovering over nextFoo
        const next: Foo<string> | undefined = nextFoo(foo) 
        foo = next // commenting this out masks the issue
    }
}

【讨论】:

  • const next: typeof foo = nextFoo(foo) 也可以,而且更简洁一些。
  • @ConnorLow 喜欢它!
猜你喜欢
  • 2019-01-01
  • 2021-08-12
  • 1970-01-01
  • 1970-01-01
  • 2018-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多