Skip to content

fix: namespaced wildcard exports should not be flagged as duplicate identifiers#3243

Open
whatfontisthis wants to merge 1 commit into
import-js:mainfrom
whatfontisthis:fix/namespaced-wildcard-export-false-positive
Open

fix: namespaced wildcard exports should not be flagged as duplicate identifiers#3243
whatfontisthis wants to merge 1 commit into
import-js:mainfrom
whatfontisthis:fix/namespaced-wildcard-export-false-positive

Conversation

@whatfontisthis

Copy link
Copy Markdown

Summary

Fixes #3220.

When a module uses export * as NS from '...', its internal names are bound under the NS namespace (i.e. NS.A, NS.B), not re-exported into the flat namespace of the current module. However, the ExportMap builder was unconditionally adding the dependency to exportMap.dependencies even for namespaced wildcard re-exports. Since dependencies is iterated as flat star-exports in ExportMap.forEach, this caused the export rule to see the internal names (e.g. A, B) as if they were directly re-exported — leading to false-positive "duplicate identifier" errors.

Example that was incorrectly reported as an error:

// AB.ts
export type A = {};
export type B = {};

// ABFeature.ts
export type * as AB from "./AB";  // A and B are under AB.*, not flat

// foo.ts
export type A = {};

// index.ts (was incorrectly flagged: "Multiple exports of name 'A'")
export * from "./ABFeature";
export * from "./foo";

Root Cause

In /src/exportMap/visitor.js, ExportAllDeclaration always added the getter to this.exportMap.dependencies. For export * as NS from '...', this is wrong — the module is aliased as a namespace, not star-re-exported. The namespace binding is correctly handled separately by processSpecifier.

Fix

Only add to dependencies when there is no exported alias on the ExportAllDeclaration node. When astNode.exported is set, it's a namespace re-export handled by processSpecifier and should not be added to flat star-export dependencies.

Test Plan

  • Added fixture files: tests/files/issue-3220-namespace-re-export/{AB.ts,ABFeature.ts,foo.ts}
  • Added a valid test case in the TypeScript context of tests/src/rules/export.js that re-exports a file containing export type * as AB from "./AB" alongside another file exporting type A — previously this triggered a false positive, now it passes cleanly
  • All 3013 existing tests continue to pass

🤖 Generated with Claude Code

@ljharb

ljharb commented May 23, 2026

Copy link
Copy Markdown
Member

This needs to be rebased; please mark it as ready for review when it is.

…espace

When a module uses `export * as NS from '...'`, the re-exported module's
internal names are namespaced under NS (e.g. NS.A), NOT re-exported into
the flat namespace. Previously, `captureDependency` was adding such modules
to `exportMap.dependencies`, which are iterated as flat star-exports.
This caused the `export` rule to incorrectly report duplicate identifiers
when a parent module did `export * from` a file containing `export * as NS`.

Fix: in `ExportAllDeclaration` visitor, only add the getter to `dependencies`
when there is no `exported` alias. When `astNode.exported` is present, the
binding is a namespace alias handled by `processSpecifier`, not a flat re-export.

Fixes import-js#3220

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@whatfontisthis whatfontisthis marked this pull request as ready for review May 25, 2026 02:50
@whatfontisthis whatfontisthis force-pushed the fix/namespaced-wildcard-export-false-positive branch from de9e030 to 8dc8a26 Compare May 25, 2026 02:50
@codecov

codecov Bot commented May 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.55%. Comparing base (dfe6ab8) to head (8dc8a26).
⚠️ Report is 6 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3243      +/-   ##
==========================================
- Coverage   95.81%   95.55%   -0.27%     
==========================================
  Files          83       83              
  Lines        3732     3732              
  Branches     1351     1351              
==========================================
- Hits         3576     3566      -10     
- Misses        156      166      +10     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Namespaced exports reported as duplicate identifiers

2 participants