microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
100.7k stars 12.45k forks source link

Spurious "referenced directly or indirectly in its own initializer" when combined with narrowing, asserts function, and loop #53955

Open jakebailey opened 1 year ago

jakebailey commented 1 year ago

Bug Report

🔎 Search Terms

referenced directly or indirectly asserts

🕗 Version & Regression Information

⏯ Playground Link

Playground Link

💻 Code

declare const myRequire: ((p: string) => {} | undefined) | undefined;

declare function assertIsDefined<T>(value: T): asserts value is NonNullable<T>

function fn1() {
    if (!myRequire) {
        return;
    }

    for (const p of ["a", "b"]) {
        // Error?
        const result = myRequire("something");
        assertIsDefined(result);
    }
}

🙁 Actual behavior

result is claimed to be referenced directly or indirectly in its initializer.

Modifying the code in various ways makes the error go away.

🙂 Expected behavior

No error; there's no relationship between the initializer and the result.

ahejlsberg commented 1 year ago

Here's what happens:

We probably could be a bit smarter about realizing that none of the arguments in the assertIsDefined(result) call match the reference (myRequire) for which we are currently doing CFA.

TomerAberbach commented 2 months ago

I'm noticing an odd "referenced directly or indirectly in its own initializer" error in my code. Wondering if you can help confirm whether this is the same issue or a separate one?

Playground link