diff --git a/crates/swc_ecma_transforms_typescript/src/strip.rs b/crates/swc_ecma_transforms_typescript/src/strip.rs index e5b82cbd48e..dba7254ed1a 100644 --- a/crates/swc_ecma_transforms_typescript/src/strip.rs +++ b/crates/swc_ecma_transforms_typescript/src/strip.rs @@ -165,7 +165,8 @@ pub fn strip_with_config(config: Config, top_level_mark: Mark) -> impl Fold + Vi is_type_only_export: Default::default(), decl_names: Default::default(), in_var_pat: Default::default(), - keys: Default::default() + keys: Default::default(), + exported_variable_to_is_type: Default::default(), }), inline_enum(ts_enum_lit, ts_enum_config) ) @@ -236,6 +237,7 @@ where decl_names: Default::default(), in_var_pat: Default::default(), keys: Default::default(), + exported_variable_to_is_type: Default::default(), }), inline_enum(ts_enum_lit, ts_enum_config) ) @@ -292,6 +294,10 @@ where in_var_pat: bool, keys: Vec, + + /// Key is the `orig` in ExportNamedSpecifier + /// Value is `true` if the Key is a type + exported_variable_to_is_type: AHashMap, } impl Strip @@ -1675,6 +1681,24 @@ where self.is_type_only_export = old; } + fn visit_export_named_specifier(&mut self, n: &ExportNamedSpecifier) { + let is_type = self.is_type_only_export || n.is_type_only; + if let ModuleExportName::Ident(local_ident) = &n.orig { + // If the stored exported `Id` is a value, we just leave it here. + // If the stored exported `Id` is both a type and value, we consider it's a + // value. See https://github.com/denoland/deno/issues/8978 + let is_type_to_the_existed = self + .exported_variable_to_is_type + .entry(local_ident.to_id()) + .or_insert(is_type); + + if *is_type_to_the_existed && !is_type { + *is_type_to_the_existed = false + } + } + n.visit_children_with(self) + } + fn visit_prop_name(&mut self, n: &PropName) { if let PropName::Computed(e) = n { e.visit_with(self) @@ -2057,8 +2081,18 @@ where import.specifiers.retain(|s| match *s { ImportSpecifier::Named(ImportNamedSpecifier { - ref is_type_only, .. - }) if *is_type_only => false, + ref is_type_only, + ref local, + .. + }) if *is_type_only + || self + .exported_variable_to_is_type + .get(&local.to_id()) + .copied() + .unwrap_or_default() => + { + false + } ImportSpecifier::Default(ImportDefaultSpecifier { ref local, .. }) | ImportSpecifier::Named(ImportNamedSpecifier { ref local, .. }) diff --git a/crates/swc_ecma_transforms_typescript/tests/fixture/issue-7076/1/input.ts b/crates/swc_ecma_transforms_typescript/tests/fixture/issue-7076/1/input.ts new file mode 100644 index 00000000000..11f913c4599 --- /dev/null +++ b/crates/swc_ecma_transforms_typescript/tests/fixture/issue-7076/1/input.ts @@ -0,0 +1,2 @@ +import { A } from "./a.ts"; +export { type A }; diff --git a/crates/swc_ecma_transforms_typescript/tests/fixture/issue-7076/1/output.js b/crates/swc_ecma_transforms_typescript/tests/fixture/issue-7076/1/output.js new file mode 100644 index 00000000000..e69de29bb2d