Skip to content

Elide namespace imports used only by type-only export aliases#4110

Draft
Copilot wants to merge 2 commits into
mainfrom
copilot/fix-namespace-import-elision
Draft

Elide namespace imports used only by type-only export aliases#4110
Copilot wants to merge 2 commits into
mainfrom
copilot/fix-namespace-import-elision

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 30, 2026

A namespace import was preserved when its only use was a type-only export import alias. This caused tsgo to emit runtime imports that TypeScript elides.

  • Alias reference tracking

    • Avoid marking a namespace import as value-referenced from the module reference of an import = alias.
    • Preserve existing value alias behavior through the existing deferred import = reference path.
  • Regression coverage

    • Added a compiler emit test for:
import * as ns from "./a";

export import A = ns.A;

which now emits:

export {};

Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix namespace import elision for type-only exports Elide namespace imports used only by type-only export aliases May 30, 2026
Copilot AI requested a review from jakebailey May 30, 2026 16:51
Comment on lines +28099 to +28101
if isPartOfImportEqualsModuleReference(location) {
return
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot Why does the old compiler not need this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The old compiler normally does not reach this case for checked TS emit: it records references during checking with specific hints (the import = declaration is marked via ReferenceHint.ExportImportEquals), rather than treating the RHS qualified name as an emitted expression. Its recursive markLinkedReferences fallback is mainly for noCheck/unchecked emit, where this pattern also preserves the import. tsgo currently relies on the recursive pass for normal import elision, so the RHS ns.A was visited and incorrectly marked ns as a value reference unless we skip import-equals module references here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The old compiler normally does not reach this case for checked TS emit: it records references during checking with specific hints (the import = declaration is marked via ReferenceHint.ExportImportEquals), rather than treating the RHS qualified name as an emitted expression. Its recursive markLinkedReferences fallback is mainly for noCheck/unchecked emit, where this pattern also preserves the import. tsgo currently relies on the recursive pass for normal import elision, so the RHS ns.A was visited and incorrectly marked ns as a value reference unless we skip import-equals module references here.

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.

Namespace import used only by a type-only export import X = ns.Y is not elided

2 participants