diff --git a/packages/babel-plugin-transform-typescript/src/index.ts b/packages/babel-plugin-transform-typescript/src/index.ts index 6daeb9fa26f3..f7e73530c74e 100644 --- a/packages/babel-plugin-transform-typescript/src/index.ts +++ b/packages/babel-plugin-transform-typescript/src/index.ts @@ -229,9 +229,23 @@ export default declare((api, opts) => { continue; } + const importsToRemove: NodePath[] = []; + const specifiersLength = stmt.node.specifiers.length; + const isAllSpecifiersElided = () => + specifiersLength > 0 && + specifiersLength === importsToRemove.length; + // If onlyRemoveTypeImports is `true`, only remove type-only imports // and exports introduced in TypeScript 3.8. if (onlyRemoveTypeImports) { + for (const specifier of stmt.node.specifiers) { + if (specifier.importKind === "type") { + const binding = stmt.scope.getBinding(specifier.local.name); + if (binding) { + importsToRemove.push(binding.path); + } + } + } NEEDS_EXPLICIT_ESM.set(path.node, false); } else { // Note: this will allow both `import { } from "m"` and `import "m";`. @@ -241,9 +255,6 @@ export default declare((api, opts) => { continue; } - let allElided = true; - const importsToRemove: NodePath[] = []; - for (const specifier of stmt.node.specifiers) { const binding = stmt.scope.getBinding(specifier.local.name); @@ -264,17 +275,16 @@ export default declare((api, opts) => { ) { importsToRemove.push(binding.path); } else { - allElided = false; NEEDS_EXPLICIT_ESM.set(path.node, false); } } + } - if (allElided) { - stmt.remove(); - } else { - for (const importPath of importsToRemove) { - importPath.remove(); - } + if (isAllSpecifiersElided()) { + stmt.remove(); + } else { + for (const importPath of importsToRemove) { + importPath.remove(); } } @@ -325,6 +335,17 @@ export default declare((api, opts) => { return; } + // remove export declaration that is filled with type-only specifiers + // export { type A1, type A2 } from "a"; + if ( + path.node.source && + path.node.specifiers.length > 0 && + path.node.specifiers.every(({ exportKind }) => exportKind === "type") + ) { + path.remove(); + return; + } + // remove export declaration if it's exporting only types // This logic is needed when exportKind is "value", because // currently the "type" keyword is optional. @@ -348,7 +369,10 @@ export default declare((api, opts) => { ExportSpecifier(path) { // remove type exports - if (!path.parent.source && isGlobalType(path, path.node.local.name)) { + if ( + (!path.parent.source && isGlobalType(path, path.node.local.name)) || + path.node.exportKind === "type" + ) { path.remove(); } }, diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-1/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-1/input.ts new file mode 100644 index 000000000000..d268127794d9 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-1/input.ts @@ -0,0 +1,2 @@ +class Foo {} +export { type Foo }; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-1/output.mjs b/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-1/output.mjs new file mode 100644 index 000000000000..736b92725dc2 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-1/output.mjs @@ -0,0 +1,3 @@ +class Foo {} + +export {}; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-2/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-2/input.ts new file mode 100644 index 000000000000..b7724a25247d --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-2/input.ts @@ -0,0 +1 @@ +export { type A1, type A2 } from "a" diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-2/output.mjs b/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-2/output.mjs new file mode 100644 index 000000000000..cb0ff5c3b541 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-2/output.mjs @@ -0,0 +1 @@ +export {}; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-3/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-3/input.ts new file mode 100644 index 000000000000..a6431530d3ac --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-3/input.ts @@ -0,0 +1 @@ +export { type A1, type A2, A3 } from "a" diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-3/output.mjs b/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-3/output.mjs new file mode 100644 index 000000000000..da23041dfb5d --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-3/output.mjs @@ -0,0 +1 @@ +export { A3 } from "a"; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/only-remove-type-imports/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/imports/only-remove-type-imports/input.ts index 744ae808eaa9..6b2b75d9f454 100644 --- a/packages/babel-plugin-transform-typescript/test/fixtures/imports/only-remove-type-imports/input.ts +++ b/packages/babel-plugin-transform-typescript/test/fixtures/imports/only-remove-type-imports/input.ts @@ -10,4 +10,6 @@ import "g"; import type H from "h"; import type { I, I2 } from "i"; import type * as J from "j"; +import { type K1, type K2 } from "k"; +import { type L1, L2, type L3 } from "l"; ; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/only-remove-type-imports/output.mjs b/packages/babel-plugin-transform-typescript/test/fixtures/imports/only-remove-type-imports/output.mjs index d86475cacac8..78a426b356b2 100644 --- a/packages/babel-plugin-transform-typescript/test/fixtures/imports/only-remove-type-imports/output.mjs +++ b/packages/babel-plugin-transform-typescript/test/fixtures/imports/only-remove-type-imports/output.mjs @@ -5,4 +5,5 @@ import d, { d2 } from "d"; import e, { e3 as e4 } from "e"; import "f"; import "g"; +import { L2 } from "l"; ; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-1/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-1/input.ts new file mode 100644 index 000000000000..e4fde7f90cb3 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-1/input.ts @@ -0,0 +1,2 @@ +import { Foo1, type Foo2 } from "Foo"; +Foo1; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-1/output.mjs b/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-1/output.mjs new file mode 100644 index 000000000000..b960b41f8c81 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-1/output.mjs @@ -0,0 +1,2 @@ +import { Foo1 } from "Foo"; +Foo1; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-2/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-2/input.ts new file mode 100644 index 000000000000..d40d26bca8f4 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-2/input.ts @@ -0,0 +1 @@ +import { type Foo1, type Foo2 } from "Foo"; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-2/output.mjs b/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-2/output.mjs new file mode 100644 index 000000000000..cb0ff5c3b541 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-2/output.mjs @@ -0,0 +1 @@ +export {};