Skip to content

Conversation

Akshit222
Copy link

@Akshit222 Akshit222 commented Sep 2, 2025

Fixes #62305

Summary

This PR fixes incorrect .d.ts emission when re-assigning explicitly annotated unique symbol properties to functions.
Previously, TypeScript would emit these properties as var, which violates TS1332 ("A variable whose type is a 'unique symbol' type must be const").
This caused invalid declarations in generated .d.ts files.

The fix ensures that unique symbol reassignments are always emitted as const in declaration files.

What was happening before

Given the following code:

const mySymbol: unique symbol = Symbol();

function myFunction() {}
myFunction.mySymbol = mySymbol;

TypeScript would emit:

declare namespace myFunction {
    var mySymbol: unique symbol; // ❌ invalid
}

This triggers TS1332 at declaration time.

What this PR changes

  • Added a helper isUniqueSymbolType in transformers/declarations.ts to detect explicit : unique symbol type annotations.
  • Updated the declaration transform so that when such a type is found, the generated variable declaration is emitted with NodeFlags.Const instead of NodeFlags.None.

File changes

  • src/compiler/transformers/declarations.ts

    • Imported TypeOperatorNode.
    • Added isUniqueSymbolType utility.
    • Updated variable declaration creation to use const when the type is explicitly unique symbol.

Tests

  • Added new test: tests/cases/compiler/uniqueSymbolReassignment.ts.

  • Included baselines:

    • tests/baselines/reference/uniqueSymbolReassignment.types
    • tests/baselines/reference/uniqueSymbolReassignment.symbols
    • tests/baselines/reference/uniqueSymbolReassignment.js

These tests confirm that explicitly annotated unique symbol reassignments are correctly emitted as const in .d.ts output.

Result

Now the same code:

const mySymbol: unique symbol = Symbol();

function myFunction() {}
myFunction.mySymbol = mySymbol;

Correctly emits:

declare namespace myFunction {
    const mySymbol: unique symbol; // ✅ fixed
}

This aligns with expected behavior and resolves the bug described in #62305.

Notes

This revised implementation avoids using the type checker or modifying the emitter, based on feedback from @jakebailey.
The fix is now limited to declarations.ts and relies only on explicit AST annotations, ensuring better scalability and external compatibility.

@typescript-bot
Copy link
Collaborator

Looks like you're introducing a change to the public API surface area. If this includes breaking changes, please document them on our wiki's API Breaking Changes page.

Also, please make sure @DanielRosenwasser and @RyanCavanaugh are aware of the changes, just as a heads up.

@Akshit222
Copy link
Author

@microsoft-github-policy-service agree

@Akshit222 Akshit222 force-pushed the fix-unique-symbol-dts branch from 39eea36 to df68016 Compare September 2, 2025 09:30
@Akshit222
Copy link
Author

Please let me know if there are any concerns with the approach, implementation, or tests. I’m happy to make adjustments based on feedback.

@jakebailey
Copy link
Member

The emitter cannot depend on the type checker like this. It won't scale well for the Go port, and it also means it's impossible to replicate TS's emit externally without having a type checker, which does not exist outside of this project.

@jakebailey
Copy link
Member

In general, I do not this approach is workable. The fix needs to come by some other means. The Printer should not contain logic like this.

@Akshit222 Akshit222 force-pushed the fix-unique-symbol-dts branch from bb35bc9 to a58eb92 Compare September 7, 2025 08:45
@Akshit222
Copy link
Author

I’ve revised this PR to follow the feedback .
The new implementation avoids using the type checker or emitter logic and instead handles explicit unique symbol annotations directly in declarations.ts.

I’ve tried to keep the change minimal and aligned with what was suggested.
If I’ve misunderstood or taken the wrong approach again, please let me know — I’m happy to adjust further.

@Akshit222 Akshit222 force-pushed the fix-unique-symbol-dts branch from a58eb92 to 3f6b576 Compare September 7, 2025 09:01
@Akshit222 Akshit222 force-pushed the fix-unique-symbol-dts branch from 354e858 to 270aaee Compare September 7, 2025 10:03
@typescript-bot typescript-bot added the For Backlog Bug PRs that fix a backlog bug label Sep 8, 2025
@github-project-automation github-project-automation bot moved this from Not started to Waiting on author in PR Backlog Sep 8, 2025
@Akshit222
Copy link
Author

Thank you for the feedback! I’ve gone through the issues raised and want to clarify the changes included in this commit:

Test files updated:
The test case tests/cases/compiler/uniqueSymbolReassignment.ts has been updated to reflect correct behavior and expected outputs. As a result, the baselines have been updated accordingly, and now include the following files in tests/baselines/reference/:

uniqueSymbolReassignment.js

uniqueSymbolReassignment.symbols

uniqueSymbolReassignment.types

These are the correct and intended baseline files for this test case. Other artifact files such as .d.ts, .d.errors.txt, and .d.types were removed because they were leftover artifacts from earlier runs and shouldn’t be tracked in the repository.

Fix in the test logic:
The original test used const declarations for non-unique symbols, which caused confusion in the emitted output and errors that did not align with the expected behavior. I corrected the declarations in the test to:

// Non-unique symbols (regular Symbol() without const)
let nonUniqueSymbol1 = Symbol('nonUnique1');
let nonUniqueSymbol2 = Symbol('nonUnique2');

By using let instead of const, the test now accurately reflects how non-unique symbols should behave, and the emitted output aligns with the correct TypeScript semantics.

Please let me know if further adjustments are needed or if any part of the test setup should be improved.

@Akshit222
Copy link
Author

if I’ve misunderstood any part of the concerns raised or if further adjustments are needed, please let me know

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
For Backlog Bug PRs that fix a backlog bug
Projects
Status: Waiting on author
Development

Successfully merging this pull request may close these issues.

Incorrect emitted declaration for unique symbol re-assignment
3 participants