diff --git a/crates/oxc_ast/src/ast_impl/js.rs b/crates/oxc_ast/src/ast_impl/js.rs index f6d5106f1051a..743dd14dacdad 100644 --- a/crates/oxc_ast/src/ast_impl/js.rs +++ b/crates/oxc_ast/src/ast_impl/js.rs @@ -1044,6 +1044,11 @@ impl<'a> Declaration<'a> { Declaration::TSImportEqualsDeclaration(_) => false, } } + + /// Returns `true` if this declaration is a TypeScript type or interface declaration. + pub fn is_type(&self) -> bool { + matches!(self, Self::TSTypeAliasDeclaration(_) | Self::TSInterfaceDeclaration(_)) + } } impl VariableDeclaration<'_> { diff --git a/crates/oxc_codegen/src/gen.rs b/crates/oxc_codegen/src/gen.rs index 6dd265596fa06..e5b34e0bde73e 100644 --- a/crates/oxc_codegen/src/gen.rs +++ b/crates/oxc_codegen/src/gen.rs @@ -1007,7 +1007,9 @@ impl Gen for ExportNamedDeclaration<'_> { p.add_source_mapping(self.span); p.print_indent(); p.print_str("export"); - if self.export_kind.is_type() { + if self.export_kind.is_type() + && !self.declaration.as_ref().is_some_and(oxc_ast::ast::Declaration::is_type) + { p.print_str(" type "); } if let Some(decl) = &self.declaration { diff --git a/crates/oxc_parser/src/js/module.rs b/crates/oxc_parser/src/js/module.rs index b9ee36cf4b0f1..9af384be3209f 100644 --- a/crates/oxc_parser/src/js/module.rs +++ b/crates/oxc_parser/src/js/module.rs @@ -363,13 +363,18 @@ impl<'a> ParserImpl<'a> { self.ctx = self.ctx.union_ambient_if(modifiers.contains_declare()); let declaration = self.parse_declaration(decl_span, &modifiers)?; + let export_kind = if declaration.is_type() { + ImportOrExportKind::Type + } else { + ImportOrExportKind::Value + }; self.ctx = reserved_ctx; Ok(self.ast.alloc_export_named_declaration( self.end_span(span), Some(declaration), self.ast.vec(), None, - ImportOrExportKind::Value, + export_kind, NONE, )) } diff --git a/crates/oxc_prettier/src/format/print/module.rs b/crates/oxc_prettier/src/format/print/module.rs index 6f0f49f5de59c..15cf8be581034 100644 --- a/crates/oxc_prettier/src/format/print/module.rs +++ b/crates/oxc_prettier/src/format/print/module.rs @@ -121,7 +121,9 @@ pub fn print_export_declaration<'a>( } } ExportDeclarationLike::ExportNamedDeclaration(decl) => { - if decl.export_kind.is_type() { + if decl.export_kind.is_type() + && !decl.declaration.as_ref().is_some_and(oxc_ast::ast::Declaration::is_type) + { parts.push(text!(" type")); } if let Some(decl) = &decl.declaration {