Fix spurious _N suffix on type parameters of sibling object-literal methods in declaration emit#3969
Merged
Merged
Conversation
…claration emit Agent-Logs-Url: https://github.com/microsoft/typescript-go/sessions/ffbe5c70-24b8-4930-b46d-854147571c2a Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
Agent-Logs-Url: https://github.com/microsoft/typescript-go/sessions/ffbe5c70-24b8-4930-b46d-854147571c2a Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Fix extra suffix in type parameters for object literal methods
Fix spurious May 18, 2026
_N suffix on type parameters of sibling object-literal methods in declaration emit
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes a declaration-emit bug in the pseudo type-node builder where per-object-literal-element scopes were accidentally nested (due to defer inside a loop), causing unnecessary _N suffixing of generic type parameter names across sibling object-literal methods in emitted .d.ts.
Changes:
- Correct scope cleanup in
pseudoTypeToNodefor object-literal elements by invoking the per-element cleanup at the end of each loop iteration (instead of deferring until function return). - Add a new compiler test covering sibling object-literal generic methods (including shared type parameter names and multi-type-parameter methods).
- Update an existing baseline to reflect the corrected emitted generic parameter name (removing the spurious suffix).
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| internal/checker/pseudotypenodebuilder.go | Fix per-element scope cleanup so sibling object-literal members don’t share type-parameter name de-duplication state. |
| testdata/tests/cases/compiler/declarationEmitObjectLiteralMethodGenericNoSuffix.ts | New repro test for object-literal sibling generic methods emitting without _N suffix. |
| testdata/baselines/reference/compiler/declarationEmitObjectLiteralMethodGenericNoSuffix.types | New baseline for the added test (types output). |
| testdata/baselines/reference/compiler/declarationEmitObjectLiteralMethodGenericNoSuffix.symbols | New baseline for the added test (symbols output). |
| testdata/baselines/reference/compiler/declarationEmitObjectLiteralMethodGenericNoSuffix.js | New baseline for the added test (JS + .d.ts output). |
| testdata/baselines/reference/compiler/declarationEmitConstObjectLiteralGenericMethod1.js | Baseline update reflecting corrected .d.ts output (T instead of T_1). |
RyanCavanaugh
approved these changes
May 19, 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.
Type parameters of sibling methods in an object literal were being renamed with a
_Nsuffix in emitted.d.tsfiles even when no name collision existed:Emitted before:
Root cause
In
pseudotypenodebuilder.go, the loop that serializes object-literal elements useddefer cleanup()to pop the per-element nodebuilder scope:Because
deferfires at function return rather than loop-iteration end, per-element scopes were nested instead of sibling. The second method'senterNewScoperan inside the first's scope, sofoo'sMwas still in the inheritedtypeParameterNamesByTextset and the de-duplicator renamedbar'sMtoM_1.Changes
internal/checker/pseudotypenodebuilder.go— Hoistcleanupto a loop-scoped variable and invoke it explicitly at the end of each iteration (afternewPropis appended), so sibling element scopes are properly siblings.testdata/tests/cases/compiler/declarationEmitObjectLiteralMethodGenericNoSuffix.tscovers the issue's repro plus shared-Tmethods and multi-type-parameter methods.declarationEmitConstObjectLiteralGenericMethod1.d.tspreviously baked in the buggyT_1output; now emitsT.