TypeScript icon indicating copy to clipboard operation
TypeScript copied to clipboard

Bizarre circular type false positive

Open MichaelMitchell-at opened this issue 2 years ago • 5 comments

Bug Report

🔎 Search Terms

implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.(7022)

🕗 Version & Regression Information

This changed between versions 4.6.2 and 4.7.0-beta

⏯ Playground Link

Playground link with relevant code

💻 Code

type Wrapper = {
    data: number | null;
};

function example(wrapper: Wrapper) {
    // The error goes away if this line is removed and `null` is removed from the type
    if (wrapper.data === null) return;

    // The error goes away if the loop body is inlined o_O
    for (const _ of []) {
        const d = wrapper.data;
        //    ^ 'd' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.

        // The error goes away without these lines o_O
        const t = d;
        const list = [0];
        if (list[t]) {}
    }
}

🙁 Actual behavior

Error: implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer

🙂 Expected behavior

No error

MichaelMitchell-at avatar Apr 14 '22 22:04 MichaelMitchell-at

cc @ahejlsberg since you made some significant type flow analysis changes

MichaelMitchell-at avatar Apr 14 '22 22:04 MichaelMitchell-at

:wave: Hi, I'm the Repro bot. I can help narrow down and track compiler bugs across releases! This comment reflects the current state of the repro in the issue body running against the nightly TypeScript.


Issue body code block by @MichaelMitchell-at

:x: Failed: -

  • 'd' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.
Historical Information
Version Reproduction Outputs
4.2.2, 4.3.2, 4.4.2, 4.5.2, 4.6.2

:+1: Compiled

typescript-bot avatar Apr 26 '22 17:04 typescript-bot

The change between 4.6.2 and Nightly occurred at 162713fac9da0304769ef0b7cfdd568f319a55ea.

typescript-bot avatar Apr 26 '22 18:04 typescript-bot

Have a similar repro; was looking to file a bug and this seems like the right place for it.

interface A {
    a?: A
}

function foo(a: A) : void {
    let working : A | undefined = a;

    while (working) {
        // 'next_A' has type 'any' because it is referenced in its own initializer
        const next_A = working.a;
        if (next_A) {
            working = next_A;
        }
    }
}

playground link

softwareCobbler avatar Jun 12 '22 02:06 softwareCobbler

I looked a bit into what part of https://github.com/microsoft/TypeScript/commit/162713fac9da0304769ef0b7cfdd568f319a55ea caused this regression. It seems like adding isEntityNameExpression(expr.argumentExpression) to isNarrowableReference allows flowNodes to be set on expressions where they weren't previously during the binding phase. This in turn seems to lead to a circular type resolution when typing the expression along the getFlowTypeOfReference code path.

I haven't looked deep enough yet to understand why the circular type resolution happens yet, but I'm sharing my findings here in case it helps someone else pick up this investigation.

MichaelMitchell-at avatar Sep 12 '22 17:09 MichaelMitchell-at

@Andarist you've been pretty capable at fixing random bugs I've stumbled upon before, so maybe this one would be of interest to you 😉

MichaelMitchell-at avatar Dec 08 '22 20:12 MichaelMitchell-at

The error also goes away if you simply move just the initialization out of the loop:

type Wrapper = {
    readonly data: number | null;
};

function example(wrapper: Wrapper) {
    if (wrapper.data === null) return;

    const d = wrapper.data;
    for (const _ of []) {
        const t = d;
        const list = [0];
        if (list[t]) {}
    }
}

Also, per the Playground link, the change happened after 4.6.4. I presume https://github.com/microsoft/TypeScript/commit/162713fac9da0304769ef0b7cfdd568f319a55ea is post 4.6.4?

vassudanagunta avatar Jun 26 '23 21:06 vassudanagunta