Skip to content

fix: preserve type modifier for export type * re-exports#216

Open
benpsnyder wants to merge 1 commit intosxzz:mainfrom
benpsnyder:fix/export-type-star-modifier
Open

fix: preserve type modifier for export type * re-exports#216
benpsnyder wants to merge 1 commit intosxzz:mainfrom
benpsnyder:fix/export-type-star-modifier

Conversation

@benpsnyder
Copy link
Copy Markdown

Problem

export type * from './mod' loses the type modifier during bundling, producing incorrect .d.ts output where re-exported names appear as value exports instead of type-only exports.

For example, given:

export type * from './all'

where ./all exports const all = 42, the bundled output was:

export { all };

instead of the correct:

export { type all };

This only affected the bare export type * form — the namespace form (export type * as ns from) already worked because Babel parses it as ExportNamedDeclaration with ExportNamespaceSpecifier, which goes through the existing type-only tracking path.

Root Cause

In rewriteImportExport(), ExportAllDeclaration nodes had their exportKind unconditionally set to 'value' so Rolldown can process them as JavaScript. But unlike ExportNamedDeclaration (which has specifiers whose names get tracked in typeOnlyIds), ExportAllDeclaration has no specifiers — so there was nothing to track, and the type-only information was silently discarded.

Fix

  1. Pre-scan the AST before rewriteImportExport runs, resolving source modules of export type * declarations and recording them in a typeOnlyStarSources set.
  2. Track exported binding names per module during transform in moduleExportBindings.
  3. In renderChunk, for any source module that was a target of export type *, add all of its exported bindings to typeOnlyIds so patchImportExport correctly restores the type modifier.

Related

Test plan

  • Existing type-only-export fixture now correctly outputs type all (snapshot updated)
  • Existing resolve-dts fixture now correctly outputs type Foo (snapshot updated)
  • rollup-plugin-dts/export-all-as-type compatibility test now correctly outputs type foo (snapshot updated)
  • Full test suite passes (196 passed, 1 expected fail)

`export type * from './mod'` was losing its type-only semantics during
bundling because `rewriteImportExport` unconditionally set
`exportKind = 'value'` on all `ExportAllDeclaration` nodes without
tracking which sources were type-only.

The fix resolves source modules of `export type *` declarations before
the modifier is stripped, then marks all of their exported bindings as
type-only during chunk rendering.

Closes sxzz#95

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

export * loses type modifiers when flattening re-exports

1 participant