Skip to content

Fix redundant undefined wrapping in declaration emit#4302

Open
jakebailey wants to merge 2 commits into
mainfrom
jabaile/fix-4079
Open

Fix redundant undefined wrapping in declaration emit#4302
jakebailey wants to merge 2 commits into
mainfrom
jabaile/fix-4079

Conversation

@jakebailey

Copy link
Copy Markdown
Member

Fixes #4079
Closes #4172

@jakebailey jakebailey marked this pull request as ready for review June 13, 2026 00:11
Copilot AI review requested due to automatic review settings June 13, 2026 00:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR aligns tsgo’s declaration emit for defaulted/optional parameters with upstream tsc by avoiding redundant | undefined wrapping (and the extra parentheses that come with it) when the serialized type already includes or could already include undefined. It adds a compiler regression test capturing the reported “curry” nested-signature case.

Changes:

  • Add a new compiler test covering primitive vs. non-primitive unions and nested “curry” signatures, with updated baselines matching tsc’s formatting.
  • Teach declaration serialization to opportunistically extend simple syntactic type nodes with | undefined (only when safe), rather than always wrapping via optional-type construction.
  • Avoid adding an extra | undefined pseudo-type wrapper when the pseudo-type may already include undefined.

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
testdata/tests/cases/compiler/declarationEmitOptionalParameterUndefined.ts New regression test reproducing the optional/defaulted parameter emit differences (including nested curry signatures).
testdata/baselines/reference/compiler/declarationEmitOptionalParameterUndefined.types Type baseline asserting the corrected, tsc-style undefined/parentheses behavior.
testdata/baselines/reference/compiler/declarationEmitOptionalParameterUndefined.symbols Symbol baseline for the new regression test.
testdata/baselines/reference/compiler/declarationEmitOptionalParameterUndefined.js JS + .d.ts baseline verifying the fixed declaration emit output.
internal/pseudochecker/lookup.go Export helper to conservatively detect type nodes that might already include undefined.
internal/checker/nodebuilderimpl.go Update declaration type serialization to avoid redundant `

//// [declarationEmitOptionalParameterUndefined.d.ts]
export declare function simple_primitive(foo: number | boolean | null | undefined, _: string): void;
export declare function simple_primitive_with_explicit_undefined(foo: number | boolean | null | undefined, _: string): void;
export declare function simple_nonPrimitive(foo: (number | RegExp | null) | undefined, _: string): void;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

By keeping the bracket on foo, is it done for matching TS 6 behavior?

But on the other hand, it is indeed redundant, in case when the parameter is purely an union of types. It may cause downstream typechecker to process a bit more lexical tokens I suppose? 😕

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

TS6 did this, yeah.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Was able to improve it

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.

Behavior difference: Notable difference regarding optional function argument type emits

3 participants