Fix TS2454 false positive for closed-over mutable variables - #63984
Queued
Mohit Nayak (mohit-nayak) wants to merge 3 commits into
Queued
Fix TS2454 false positive for closed-over mutable variables#63984Mohit Nayak (mohit-nayak) wants to merge 3 commits into
Mohit Nayak (mohit-nayak) wants to merge 3 commits into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes a TS2454 false positive by ensuring assignment analysis runs for the variable’s declaring container.
Changes:
- Removes an unsafe symbol-level early return.
- Adds regression and negative test cases.
- Records expected diagnostic, type, and symbol baselines.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
tsc/internal/checker/flow.go |
Corrects assignment-marking behavior. |
tsc/testdata/tests/cases/compiler/definiteAssignmentOfClosedOverVariable.ts |
Adds regression coverage. |
tsc/testdata/baselines/reference/compiler/definiteAssignmentOfClosedOverVariable.errors.txt |
Captures the remaining valid diagnostic. |
tsc/testdata/baselines/reference/compiler/definiteAssignmentOfClosedOverVariable.types |
Records inferred types. |
tsc/testdata/baselines/reference/compiler/definiteAssignmentOfClosedOverVariable.symbols |
Records symbol resolution. |
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
Author
|
@microsoft-github-policy-service agree |
Copilot started reviewing on behalf of
Ryan Cavanaugh (RyanCavanaugh)
August 24, 2026 19:43
View session
Anders Hejlsberg (ahejlsberg)
approved these changes
Aug 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #63981
Problem
Under --strict, a top-level let that is assigned at the top level gets reported as used before assignment when a closure compound-assigns it:
count is assigned before the callback can ever run, and the reference inside the arrow is an outer-variable reference, so definite assignment analysis should not fire here. 5.7 and 6.0 both accept this. The error is new in 7.
Cause
ensureAssignmentsMarked returned early whenever the symbol already had a non-zero lastAssignmentPos. That is not a safe "already computed" signal, because lastAssignmentPos can be written by a walk of a nested function that never visits the declaring container.
What happens in the repro:
Strada has no equivalent early return. Its only guard is the AssignmentsMarked node-links flag on the declaring container, which is per-container and therefore correct.
Solution
Drop the early return. The AssignmentsMarked flag together with hasParentWithAssignmentsMarked already guarantees each container is walked at most once, so the removed check only saved one FindAncestor and a map lookup, and it did that by skipping the walk that produces the right answer. This puts the behavior back in line with Strada.
Tests
Added tsc/testdata/tests/cases/compiler/definiteAssignmentOfClosedOverVariable.ts with three cases:
The baseline has exactly one diagnostic, on the third case. Running the same file through tsc@5.7.3 gives the identical single error on the identical line, so the port now matches Strada in both directions.
Across the full suite the only baselines written were the three for this new test, so nothing else moved. That is worth noting because ensureAssignmentsMarked also feeds isSymbolAssigned and isPastLastAssignment, which affect narrowing of closed-over variables and not just TS2454.
Checklist
TS2454false positive when a callback mutates an outerletand returns the enclosing function's parameter #63981 has not been triaged yet, so it has no milestone. I cannot set one. Happy to wait for triage if you would rather look at the issue first.