Skip to content

Commit

Permalink
fix: strip type only ts module
Browse files Browse the repository at this point in the history
  • Loading branch information
magic-akari committed May 12, 2023
1 parent 2a39bd8 commit ad1dcf0
Showing 1 changed file with 85 additions and 18 deletions.
103 changes: 85 additions & 18 deletions crates/swc_ecma_transforms_typescript/src/strip_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,26 +173,10 @@ impl VisitMut for StripType {

fn should_retain_module_item(module_item: &ModuleItem) -> bool {
match module_item {
ModuleItem::ModuleDecl(ModuleDecl::Import(import_decl)) => !import_decl.type_only,
ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(export_decl)) => {
should_retain_decl(&export_decl.decl)
}
ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(named_export)) => !named_export.type_only,
ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultDecl(export_default_decl)) => {
!export_default_decl.decl.is_ts_interface_decl()
}
ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultExpr(..)) => true,
ModuleItem::ModuleDecl(ModuleDecl::ExportAll(export_all)) => !export_all.type_only,
ModuleItem::ModuleDecl(ModuleDecl::TsImportEquals(ts_import_equals)) => {
!ts_import_equals.is_type_only
}
ModuleItem::ModuleDecl(ModuleDecl::TsExportAssignment(..)) => true,
ModuleItem::ModuleDecl(ModuleDecl::TsNamespaceExport(..)) => {
// https://www.typescriptlang.org/docs/handbook/modules.html#umd-modules
// `TsNamespaceExport` is only used in UMD dts
false
}
ModuleItem::Stmt(stmt) => !stmt.is_empty(),
_ => !module_item.is_type_only(),
}
}

Expand All @@ -204,6 +188,89 @@ fn should_retain_decl(decl: &Decl) -> bool {
Decl::TsInterface(..) => false,
Decl::TsTypeAlias(..) => false,
Decl::TsEnum(ts_enum) => !ts_enum.declare,
Decl::TsModule(ts_module) => !ts_module.declare,
Decl::TsModule(ts_module) => should_retain_ts_module(ts_module),
}
}

fn should_retain_ts_module(ts_module: &TsModuleDecl) -> bool {
if ts_module.declare || ts_module.global {
return false;
}

!ts_module.is_type_only()
}

trait IsTypeOnly {
fn is_type_only(&self) -> bool;
}

impl IsTypeOnly for TsModuleDecl {
fn is_type_only(&self) -> bool {
self.body
.as_ref()
.map(|body| body.is_type_only())
.unwrap_or(true)
}
}

impl IsTypeOnly for TsNamespaceBody {
fn is_type_only(&self) -> bool {
match self {
Self::TsModuleBlock(ts_module_block) => {
ts_module_block.body.iter().all(|item| item.is_type_only())
}
Self::TsNamespaceDecl(ts_namespace_decl) => ts_namespace_decl.body.is_type_only(),
}
}
}

impl IsTypeOnly for ModuleItem {
fn is_type_only(&self) -> bool {
match self {
Self::ModuleDecl(module_decl) => module_decl.is_type_only(),
Self::Stmt(stmt) => stmt.is_type_only(),
}
}
}

impl IsTypeOnly for ModuleDecl {
fn is_type_only(&self) -> bool {
match self {
Self::Import(import_decl) => import_decl.type_only,
Self::ExportDecl(export_decl) => export_decl.decl.is_type_only(),
Self::ExportNamed(named_export) => named_export.type_only,
Self::ExportDefaultDecl(export_default_decl) => {
!export_default_decl.decl.is_ts_interface_decl()
}
Self::ExportDefaultExpr(..) => false,
Self::ExportAll(export_all) => export_all.type_only,
Self::TsImportEquals(ts_import_equals) => ts_import_equals.is_type_only,
Self::TsExportAssignment(..) => false,
Self::TsNamespaceExport(..) => true,
}
}
}

impl IsTypeOnly for Decl {
fn is_type_only(&self) -> bool {
match self {
Self::TsInterface(..) => true,
Self::TsTypeAlias(..) => true,
Self::Fn(r#fn) => r#fn.function.body.is_none(),
Self::Class(..) => false,
Self::Var(..) => false,
Self::TsEnum(..) => false,
Self::TsModule(ts_module) => ts_module.is_type_only(),
}
}
}

impl IsTypeOnly for Stmt {
fn is_type_only(&self) -> bool {
match self {
Stmt::Empty(..) => true,
Stmt::Decl(decl) => decl.is_type_only(),
_ => false,
}
}
}

0 comments on commit ad1dcf0

Please sign in to comment.