Skip to content

Fix spurious _N suffix on type parameters of sibling object-literal methods in declaration emit#3969

Merged
RyanCavanaugh merged 3 commits into
mainfrom
copilot/fix-type-parameter-suffix
May 19, 2026
Merged

Fix spurious _N suffix on type parameters of sibling object-literal methods in declaration emit#3969
RyanCavanaugh merged 3 commits into
mainfrom
copilot/fix-type-parameter-suffix

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 18, 2026

Type parameters of sibling methods in an object literal were being renamed with a _N suffix in emitted .d.ts files even when no name collision existed:

export const o = {
    foo<M extends string>(): void {},
    bar<M extends string>(): void {},
};

Emitted before:

export declare const o: {
    foo<M extends string>(): void;
    bar<M_1 extends string>(): void; // should be M
};

Root cause

In pseudotypenodebuilder.go, the loop that serializes object-literal elements used defer cleanup() to pop the per-element nodebuilder scope:

for _, e := range elements {
    if e.Kind != pseudochecker.PseudoObjectElementKindPropertyAssignment {
        cleanup := b.enterNewScope(...)
        defer cleanup() // runs at function return, not loop end
    }
    ...
}

Because defer fires at function return rather than loop-iteration end, per-element scopes were nested instead of sibling. The second method's enterNewScope ran inside the first's scope, so foo's M was still in the inherited typeParameterNamesByText set and the de-duplicator renamed bar's M to M_1.

Changes

  • internal/checker/pseudotypenodebuilder.go — Hoist cleanup to a loop-scoped variable and invoke it explicitly at the end of each iteration (after newProp is appended), so sibling element scopes are properly siblings.
  • New testtestdata/tests/cases/compiler/declarationEmitObjectLiteralMethodGenericNoSuffix.ts covers the issue's repro plus shared-T methods and multi-type-parameter methods.
  • Baseline updatedeclarationEmitConstObjectLiteralGenericMethod1.d.ts previously baked in the buggy T_1 output; now emits T.

Copilot AI changed the title [WIP] Fix extra suffix in type parameters for object literal methods Fix spurious _N suffix on type parameters of sibling object-literal methods in declaration emit May 18, 2026
Copilot AI requested a review from jakebailey May 18, 2026 16:21
Copy link
Copy Markdown
Member

@jakebailey jakebailey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yikes, oops

@jakebailey jakebailey marked this pull request as ready for review May 18, 2026 16:26
Copilot AI review requested due to automatic review settings May 18, 2026 16:26
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 pseudoTypeToNode for 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 RyanCavanaugh added this pull request to the merge queue May 19, 2026
Merged via the queue into main with commit 431937b May 19, 2026
25 checks passed
@RyanCavanaugh RyanCavanaugh deleted the copilot/fix-type-parameter-suffix branch May 19, 2026 16:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Type parameters in object literal methods get extra unnecessary suffix in declaration files

4 participants