TypeScript icon indicating copy to clipboard operation
TypeScript copied to clipboard

`for`-`let` + inner function incorrectly says variable is used before being assigned

Open monsanto opened this issue 10 months ago • 0 comments

🔎 Search Terms

TS2454

🕗 Version & Regression Information

  • This changed between versions 5.6.3 and 5.7.3
  • This changed in commit or PR 533ed3d665c4bb0ecb08dd2eae95fe0aa2e1c973

⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.8.2#code/PTAEFECdIe0goAZnUAKANgUwC6gB6gyKgDaAjADSgBMAugJSgDe8oboiArgHYDG2ASxjcOqRi3aT8AblbsAvvEXwQoAPIBpUAHcB2ABagAhtBjaOPfkO5IUGHPkLFyVOuLlssuYgF40jHwA+Zg8pPFlJRWVVTR09Q15hAGdsW0g0RO4UxyJSShoGEMkuPkFhUABzMSKpNnDQqKA

💻 Code

// Error
for (let x of [1, 2]) {
    function f() {
        x;
    }
}

// OK with arrow function
for (let x of [1, 2]) {
    let f = () => {
        x;
    }
}

// OK with const
for (const x of [1, 2]) {
    function g() {
        x;
    }
}

🙁 Actual behavior

test.ts:5:9 - error TS2454: Variable 'x' is used before being assigned.

5         x;
          ~

let variables bound in the head of for are always assigned in the body.

🙂 Expected behavior

No errors.

Additional information about the issue

First noticed when upgrading from 5.6 to 5.7, was lazy and figured someone else would report it.

I figured TS might be incorrectly thinking f could be hoisted out of the loop, but it accepts it with const, so I don't know.

Commit found with

every-ts bisect start
every-ts bisect good v5.6.3
every-ts bisect bad v5.7.3
every-ts bisect run tsc --strict -m preserve test.ts -t esnext

monsanto avatar Mar 07 '25 18:03 monsanto