🔎 Search Terms
TS2454, used before being assigned, definite assignment, definite assignment analysis,
control flow analysis, closure, captured variable, outer variable, compound assignment,
strictNullChecks, false positive, tsgo, TypeScript 7
🕗 Version & Regression Information
- Fails:
typescript@7.0.2 (stable), typescript@7.1.0-dev.20260822.1, @typescript/native-preview@7.0.0-dev.20260421.2, @typescript/native-preview@7.0.0-dev.20260707.2
- Works:
typescript@6.0.3 and typescript@5.7.3
⏯ Playground Link
https://www.typescriptlang.org/play/?ts=6.0.3&strict=true&target=99&module=99&moduleResolutio
💻 Code
export {};
let count: number;
function makeCallback(p: string) {
return () => {
count += 1;
return p;
};
}
count = 0;
makeCallback('x')();
Compiled with --strict --noEmit --target esnext --module esnext --moduleResolution bundler
🙁 Actual behavior
TypeScript 7 reports:
minimal2.ts(7,5): error TS2454: Variable 'count' is used before being assigned.
🙂 Expected behavior
No error, as in 5.7 and 6.0. count is declared outside the arrow function, so the reference inside the closure is an "outer variable" reference and definite-assignment analysis should be suppressed for it. count is also definitely assigned at module top level before the callback can run.
Additional information about the issue
Each of these single changes, in isolation, makes the error disappear:
| Variation |
TS 7 |
return 'x' instead of return p |
✅ clean |
count = 1 instead of count += 1 |
✅ clean |
count = 0 moved above makeCallback |
✅ clean |
removing export {} (script rather than module) |
✅ clean |
So it seems to need all of: a module; a compound assignment to an uninitialized outer let
inside a closure; that closure returning a parameter of the enclosing function declaration;
and the outer assignment appearing after that declaration.
Found while migrating a real codebase from 5.7 to 7. It's a common test shape — a counter
incremented inside a mock callback that returns a canned response, reset in beforeEach — and
produced six errors in one test file that 5.7 and 6.0 both accept.
🔎 Search Terms
TS2454, used before being assigned, definite assignment, definite assignment analysis,
control flow analysis, closure, captured variable, outer variable, compound assignment,
strictNullChecks, false positive, tsgo, TypeScript 7
🕗 Version & Regression Information
typescript@7.0.2(stable),typescript@7.1.0-dev.20260822.1,@typescript/native-preview@7.0.0-dev.20260421.2,@typescript/native-preview@7.0.0-dev.20260707.2typescript@6.0.3andtypescript@5.7.3⏯ Playground Link
https://www.typescriptlang.org/play/?ts=6.0.3&strict=true&target=99&module=99&moduleResolutio
💻 Code
Compiled with
--strict --noEmit --target esnext --module esnext --moduleResolution bundler🙁 Actual behavior
TypeScript 7 reports:
🙂 Expected behavior
No error, as in 5.7 and 6.0.
countis declared outside the arrow function, so the reference inside the closure is an "outer variable" reference and definite-assignment analysis should be suppressed for it.countis also definitely assigned at module top level before the callback can run.Additional information about the issue
Each of these single changes, in isolation, makes the error disappear:
return 'x'instead ofreturn pcount = 1instead ofcount += 1count = 0moved abovemakeCallbackexport {}(script rather than module)So it seems to need all of: a module; a compound assignment to an uninitialized outer
letinside a closure; that closure returning a parameter of the enclosing function declaration;
and the outer assignment appearing after that declaration.
Found while migrating a real codebase from 5.7 to 7. It's a common test shape — a counter
incremented inside a mock callback that returns a canned response, reset in
beforeEach— andproduced six errors in one test file that 5.7 and 6.0 both accept.