Skip to content

Commit 6194044

Browse files
authoredNov 6, 2024··
feat(typescript): Port deno isolatedDeclarations updates (#9712)
In https://github.com/denoland/deno_graph/commits/main/src/fast_check/transform_dts.rs: From denoland/deno_graph@7f38d56 to denoland/deno_graph@258186c PR list: - [x] ~denoland/deno_graph#508. I don't port this pr because swc doesn't resolve `public_ranges`. However, I refer to https://github.com/oxc-project/oxc/blob/fac5042afafc6e1acd6953150f3857d086ba945d/crates/oxc_isolated_declarations/src/lib.rs#L421C24-L421C33 to fix the bugs. - [x] denoland/deno_graph#521 - [x] denoland/deno_graph#522 - [x] denoland/deno_graph#540 I will port the tests if I have spare time.
1 parent b49317a commit 6194044

File tree

4 files changed

+373
-135
lines changed

4 files changed

+373
-135
lines changed
 

‎.changeset/witty-bears-attend.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
swc_typescript: major
3+
---
4+
5+
feat(typescript): port deno `isolatedDeclarations` updates

‎crates/swc/src/lib.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -971,22 +971,21 @@ impl Compiler {
971971
Default::default()
972972
};
973973

974-
let dts_code = if emit_dts && program.is_module() {
974+
let dts_code = if emit_dts {
975975
let (leading, trailing) = comments.borrow_all();
976976

977977
let leading = std::rc::Rc::new(RefCell::new(leading.clone()));
978978
let trailing = std::rc::Rc::new(RefCell::new(trailing.clone()));
979979

980980
let comments = SingleThreadedComments::from_leading_and_trailing(leading, trailing);
981981
let mut checker = FastDts::new(fm.name.clone());
982-
let mut module = program.clone();
982+
let mut program = program.clone();
983983

984984
if let Some((base, resolver)) = config.resolver {
985-
module.mutate(import_rewriter(base, resolver));
985+
program.mutate(import_rewriter(base, resolver));
986986
}
987987

988-
let mut module = module.expect_module();
989-
let issues = checker.transform(&mut module);
988+
let issues = checker.transform(&mut program);
990989

991990
for issue in issues {
992991
let range = issue.range();
@@ -995,7 +994,8 @@ impl Compiler {
995994
.struct_span_err(range.span, &issue.to_string())
996995
.emit();
997996
}
998-
let dts_code = to_code_with_comments(Some(&comments), &module);
997+
998+
let dts_code = to_code_with_comments(Some(&comments), &program);
999999
Some(dts_code)
10001000
} else {
10011001
None

‎crates/swc_typescript/src/fast_dts/mod.rs

+271-125
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ use std::{mem::take, sync::Arc};
33
use swc_atoms::Atom;
44
use swc_common::{util::take::Take, FileName, Span, Spanned, DUMMY_SP};
55
use swc_ecma_ast::{
6-
BindingIdent, ClassMember, Decl, DefaultDecl, ExportDecl, ExportDefaultDecl, ExportDefaultExpr,
7-
Expr, FnDecl, FnExpr, Ident, Lit, MethodKind, Module, ModuleDecl, ModuleItem, OptChainBase,
8-
Pat, Prop, PropName, PropOrSpread, Stmt, TsEntityName, TsFnOrConstructorType, TsFnParam,
9-
TsFnType, TsKeywordType, TsKeywordTypeKind, TsLit, TsLitType, TsNamespaceBody,
10-
TsPropertySignature, TsTupleElement, TsTupleType, TsType, TsTypeAnn, TsTypeElement, TsTypeLit,
11-
TsTypeOperator, TsTypeOperatorOp, TsTypeRef, VarDecl, VarDeclKind, VarDeclarator,
6+
AssignPat, BindingIdent, ClassMember, ComputedPropName, Decl, DefaultDecl, ExportDecl,
7+
ExportDefaultExpr, Expr, Ident, Lit, MethodKind, ModuleDecl, ModuleItem, OptChainBase, Param,
8+
ParamOrTsParamProp, Pat, Program, Prop, PropName, PropOrSpread, Stmt, TsEntityName,
9+
TsFnOrConstructorType, TsFnParam, TsFnType, TsKeywordType, TsKeywordTypeKind, TsLit, TsLitType,
10+
TsNamespaceBody, TsParamPropParam, TsPropertySignature, TsTupleElement, TsTupleType, TsType,
11+
TsTypeAnn, TsTypeElement, TsTypeLit, TsTypeOperator, TsTypeOperatorOp, TsTypeRef, VarDecl,
12+
VarDeclKind, VarDeclarator,
1213
};
1314

1415
use crate::diagnostic::{DtsIssue, SourceRange};
@@ -71,10 +72,32 @@ impl FastDts {
7172
}
7273

7374
impl FastDts {
74-
pub fn transform(&mut self, module: &mut Module) -> Vec<DtsIssue> {
75+
pub fn transform(&mut self, program: &mut Program) -> Vec<DtsIssue> {
7576
self.is_top_level = true;
7677

77-
self.transform_module_items(&mut module.body);
78+
match program {
79+
Program::Module(module) => {
80+
self.transform_module_items(&mut module.body);
81+
}
82+
Program::Script(script) => {
83+
let mut last_function_name: Option<Atom> = None;
84+
script.body.retain_mut(|stmt| {
85+
if let Some(fn_decl) = stmt.as_decl().and_then(|decl| decl.as_fn_decl()) {
86+
if fn_decl.function.body.is_some() {
87+
if last_function_name
88+
.as_ref()
89+
.is_some_and(|last_name| last_name == &fn_decl.ident.sym)
90+
{
91+
return false;
92+
}
93+
} else {
94+
last_function_name = Some(fn_decl.ident.sym.clone());
95+
}
96+
}
97+
self.transform_module_stmt(stmt)
98+
})
99+
}
100+
}
78101

79102
take(&mut self.diagnostics)
80103
}
@@ -83,28 +106,10 @@ impl FastDts {
83106
let orig_items = take(items);
84107
let mut new_items = Vec::with_capacity(orig_items.len());
85108

86-
let mut prev_is_overload = false;
109+
let mut last_function_name: Option<Atom> = None;
110+
let mut is_export_default_function_overloads = false;
87111

88112
for mut item in orig_items {
89-
let is_overload = match &item {
90-
ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl { decl, .. }))
91-
| ModuleItem::Stmt(Stmt::Decl(decl)) => match decl {
92-
Decl::Fn(FnDecl {
93-
function, declare, ..
94-
}) => !declare && function.body.is_none(),
95-
_ => false,
96-
},
97-
98-
ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultDecl(ExportDefaultDecl {
99-
decl,
100-
..
101-
})) => {
102-
matches!(decl, DefaultDecl::Fn(FnExpr { function, .. }) if function.body.is_none())
103-
}
104-
105-
_ => false,
106-
};
107-
108113
match &mut item {
109114
// Keep all these
110115
ModuleItem::ModuleDecl(
@@ -116,14 +121,39 @@ impl FastDts {
116121
| ModuleDecl::ExportAll(_),
117122
) => new_items.push(item),
118123

124+
ModuleItem::Stmt(stmt) => {
125+
if let Some(fn_decl) = stmt.as_decl().and_then(|decl| decl.as_fn_decl()) {
126+
if fn_decl.function.body.is_some() {
127+
if last_function_name
128+
.as_ref()
129+
.is_some_and(|last_name| last_name == &fn_decl.ident.sym)
130+
{
131+
continue;
132+
}
133+
} else {
134+
last_function_name = Some(fn_decl.ident.sym.clone());
135+
}
136+
}
137+
138+
if self.transform_module_stmt(stmt) {
139+
new_items.push(item);
140+
}
141+
}
142+
119143
ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
120144
span, decl, ..
121145
})) => {
122-
let should_keep = prev_is_overload && !is_overload;
123-
124-
if should_keep {
125-
prev_is_overload = is_overload;
126-
continue;
146+
if let Some(fn_decl) = decl.as_fn_decl() {
147+
if fn_decl.function.body.is_some() {
148+
if last_function_name
149+
.as_ref()
150+
.is_some_and(|last_name| last_name == &fn_decl.ident.sym)
151+
{
152+
continue;
153+
}
154+
} else {
155+
last_function_name = Some(fn_decl.ident.sym.clone());
156+
}
127157
}
128158

129159
if let Some(()) = self.decl_to_type_decl(decl) {
@@ -142,6 +172,17 @@ impl FastDts {
142172
}
143173

144174
ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultDecl(export)) => {
175+
if let Some(fn_expr) = export.decl.as_fn_expr() {
176+
if is_export_default_function_overloads && fn_expr.function.body.is_some() {
177+
is_export_default_function_overloads = false;
178+
continue;
179+
} else {
180+
is_export_default_function_overloads = true;
181+
}
182+
} else {
183+
is_export_default_function_overloads = false;
184+
}
185+
145186
match &mut export.decl {
146187
DefaultDecl::Class(class_expr) => {
147188
self.class_body_to_type(&mut class_expr.class.body);
@@ -152,22 +193,10 @@ impl FastDts {
152193
DefaultDecl::TsInterfaceDecl(_) => {}
153194
};
154195

155-
let should_keep = prev_is_overload && !is_overload;
156-
prev_is_overload = is_overload;
157-
if should_keep {
158-
continue;
159-
}
160-
161196
new_items.push(item);
162197
}
163198

164199
ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultExpr(export)) => {
165-
let should_keep = prev_is_overload && !is_overload;
166-
prev_is_overload = is_overload;
167-
if should_keep {
168-
continue;
169-
}
170-
171200
let name = self.gen_unique_name();
172201
let name_ident = Ident::new_no_ctxt(name, DUMMY_SP);
173202
let type_ann = self
@@ -212,32 +241,29 @@ impl FastDts {
212241
)
213242
}
214243
}
244+
}
245+
}
215246

216-
ModuleItem::Stmt(Stmt::Decl(decl)) => match decl {
217-
Decl::TsEnum(_)
218-
| Decl::Class(_)
219-
| Decl::Fn(_)
220-
| Decl::Var(_)
221-
| Decl::TsModule(_) => {
222-
if let Some(()) = self.decl_to_type_decl(decl) {
223-
new_items.push(item);
224-
} else {
225-
self.mark_diagnostic_unable_to_infer(decl.span())
226-
}
227-
}
247+
*items = new_items;
248+
}
228249

229-
Decl::TsInterface(_) | Decl::TsTypeAlias(_) | Decl::Using(_) => {
230-
new_items.push(item);
231-
}
232-
},
250+
fn transform_module_stmt(&mut self, stmt: &mut Stmt) -> bool {
251+
let Stmt::Decl(ref mut decl) = stmt else {
252+
return false;
253+
};
233254

234-
ModuleItem::Stmt(..) => {}
255+
match decl {
256+
Decl::TsEnum(_) | Decl::Class(_) | Decl::Fn(_) | Decl::Var(_) | Decl::TsModule(_) => {
257+
if let Some(()) = self.decl_to_type_decl(decl) {
258+
true
259+
} else {
260+
self.mark_diagnostic_unable_to_infer(decl.span());
261+
false
262+
}
235263
}
236264

237-
prev_is_overload = is_overload;
265+
Decl::TsInterface(_) | Decl::TsTypeAlias(_) | Decl::Using(_) => true,
238266
}
239-
240-
*items = new_items;
241267
}
242268

243269
fn expr_to_ts_type(
@@ -445,64 +471,7 @@ impl FastDts {
445471
Decl::Fn(fn_decl) => {
446472
fn_decl.function.body = None;
447473
fn_decl.declare = is_declare;
448-
449-
for param in &mut fn_decl.function.params {
450-
match &mut param.pat {
451-
Pat::Ident(ident) => {
452-
if ident.type_ann.is_none() {
453-
self.mark_diagnostic_any_fallback(ident.span());
454-
ident.type_ann = Some(any_type_ann());
455-
}
456-
}
457-
Pat::Assign(assign_pat) => {
458-
match &mut *assign_pat.left {
459-
Pat::Ident(ident) => {
460-
if ident.type_ann.is_none() {
461-
ident.type_ann = self.infer_expr_fallback_any(
462-
assign_pat.right.take(),
463-
false,
464-
false,
465-
);
466-
}
467-
468-
ident.optional = true;
469-
param.pat = ident.clone().into();
470-
}
471-
Pat::Array(arr_pat) => {
472-
if arr_pat.type_ann.is_none() {
473-
arr_pat.type_ann = self.infer_expr_fallback_any(
474-
assign_pat.right.take(),
475-
false,
476-
false,
477-
);
478-
}
479-
480-
arr_pat.optional = true;
481-
param.pat = arr_pat.clone().into();
482-
}
483-
Pat::Object(obj_pat) => {
484-
if obj_pat.type_ann.is_none() {
485-
obj_pat.type_ann = self.infer_expr_fallback_any(
486-
assign_pat.right.take(),
487-
false,
488-
false,
489-
);
490-
}
491-
492-
obj_pat.optional = true;
493-
param.pat = obj_pat.clone().into();
494-
}
495-
Pat::Rest(_) | Pat::Assign(_) | Pat::Expr(_) | Pat::Invalid(_) => {}
496-
};
497-
}
498-
Pat::Array(_)
499-
| Pat::Rest(_)
500-
| Pat::Object(_)
501-
| Pat::Invalid(_)
502-
| Pat::Expr(_) => {}
503-
}
504-
}
505-
474+
self.handle_func_params(&mut fn_decl.function.params);
506475
Some(())
507476
}
508477
Decl::Var(var_decl) => {
@@ -748,7 +717,8 @@ impl FastDts {
748717
.into_iter()
749718
.filter(|member| match member {
750719
ClassMember::Constructor(class_constructor) => {
751-
let is_overload = class_constructor.body.is_none();
720+
let is_overload =
721+
class_constructor.body.is_none() && !class_constructor.is_optional;
752722
if !prev_is_overload || is_overload {
753723
prev_is_overload = is_overload;
754724
true
@@ -758,7 +728,8 @@ impl FastDts {
758728
}
759729
}
760730
ClassMember::Method(method) => {
761-
let is_overload = method.function.body.is_none() && !method.is_abstract;
731+
let is_overload = method.function.body.is_none()
732+
&& !(method.is_abstract || method.is_optional);
762733
if !prev_is_overload || is_overload {
763734
prev_is_overload = is_overload;
764735
true
@@ -781,16 +752,30 @@ impl FastDts {
781752
.filter_map(|member| match member {
782753
ClassMember::Constructor(mut class_constructor) => {
783754
class_constructor.body = None;
755+
self.handle_ts_param_props(&mut class_constructor.params);
784756
Some(ClassMember::Constructor(class_constructor))
785757
}
786758
ClassMember::Method(mut method) => {
759+
if let Some(new_prop_name) = valid_prop_name(&method.key) {
760+
method.key = new_prop_name;
761+
} else {
762+
return None;
763+
}
764+
787765
method.function.body = None;
788766
if method.kind == MethodKind::Setter {
789767
method.function.return_type = None;
790768
}
769+
self.handle_func_params(&mut method.function.params);
791770
Some(ClassMember::Method(method))
792771
}
793772
ClassMember::ClassProp(mut prop) => {
773+
if let Some(new_prop_name) = valid_prop_name(&prop.key) {
774+
prop.key = new_prop_name;
775+
} else {
776+
return None;
777+
}
778+
794779
if prop.type_ann.is_none() {
795780
if let Some(value) = prop.value {
796781
prop.type_ann = self
@@ -821,6 +806,101 @@ impl FastDts {
821806
*body = new_body;
822807
}
823808

809+
fn handle_ts_param_props(&mut self, param_props: &mut Vec<ParamOrTsParamProp>) {
810+
for param in param_props {
811+
match param {
812+
ParamOrTsParamProp::TsParamProp(param) => {
813+
match &mut param.param {
814+
TsParamPropParam::Ident(ident) => {
815+
self.handle_func_param_ident(ident);
816+
}
817+
TsParamPropParam::Assign(assign) => {
818+
if let Some(new_pat) = self.handle_func_param_assign(assign) {
819+
match new_pat {
820+
Pat::Ident(new_ident) => {
821+
param.param = TsParamPropParam::Ident(new_ident)
822+
}
823+
Pat::Assign(new_assign) => {
824+
param.param = TsParamPropParam::Assign(new_assign)
825+
}
826+
Pat::Rest(_)
827+
| Pat::Object(_)
828+
| Pat::Array(_)
829+
| Pat::Invalid(_)
830+
| Pat::Expr(_) => {
831+
// should never happen for parameter properties
832+
unreachable!();
833+
}
834+
}
835+
}
836+
}
837+
}
838+
}
839+
ParamOrTsParamProp::Param(param) => self.handle_func_param(param),
840+
}
841+
}
842+
}
843+
844+
fn handle_func_params(&mut self, params: &mut Vec<Param>) {
845+
for param in params {
846+
self.handle_func_param(param);
847+
}
848+
}
849+
850+
fn handle_func_param(&mut self, param: &mut Param) {
851+
match &mut param.pat {
852+
Pat::Ident(ident) => {
853+
self.handle_func_param_ident(ident);
854+
}
855+
Pat::Assign(assign_pat) => {
856+
if let Some(new_pat) = self.handle_func_param_assign(assign_pat) {
857+
param.pat = new_pat;
858+
}
859+
}
860+
Pat::Array(_) | Pat::Rest(_) | Pat::Object(_) | Pat::Invalid(_) | Pat::Expr(_) => {}
861+
}
862+
}
863+
864+
fn handle_func_param_ident(&mut self, ident: &mut BindingIdent) {
865+
if ident.type_ann.is_none() {
866+
self.mark_diagnostic_any_fallback(ident.span());
867+
ident.type_ann = Some(any_type_ann());
868+
}
869+
}
870+
871+
fn handle_func_param_assign(&mut self, assign_pat: &mut AssignPat) -> Option<Pat> {
872+
match &mut *assign_pat.left {
873+
Pat::Ident(ident) => {
874+
if ident.type_ann.is_none() {
875+
ident.type_ann =
876+
self.infer_expr_fallback_any(assign_pat.right.take(), false, false);
877+
}
878+
879+
ident.optional = true;
880+
Some(Pat::Ident(ident.clone()))
881+
}
882+
Pat::Array(arr_pat) => {
883+
if arr_pat.type_ann.is_none() {
884+
arr_pat.type_ann =
885+
self.infer_expr_fallback_any(assign_pat.right.take(), false, false);
886+
}
887+
888+
arr_pat.optional = true;
889+
Some(Pat::Array(arr_pat.clone()))
890+
}
891+
Pat::Object(obj_pat) => {
892+
if obj_pat.type_ann.is_none() {
893+
obj_pat.type_ann =
894+
self.infer_expr_fallback_any(assign_pat.right.take(), false, false);
895+
}
896+
897+
obj_pat.optional = true;
898+
Some(Pat::Object(obj_pat.clone()))
899+
}
900+
Pat::Rest(_) | Pat::Assign(_) | Pat::Expr(_) | Pat::Invalid(_) => None,
901+
}
902+
}
903+
824904
fn pat_to_ts_fn_param(&mut self, pat: Pat) -> Option<TsFnParam> {
825905
match pat {
826906
Pat::Ident(binding_id) => Some(TsFnParam::Ident(binding_id)),
@@ -939,3 +1019,69 @@ fn maybe_lit_to_ts_type(lit: &Lit) -> Option<Box<TsType>> {
9391019
Lit::JSXText(_) => None,
9401020
}
9411021
}
1022+
1023+
fn valid_prop_name(prop_name: &PropName) -> Option<PropName> {
1024+
fn prop_name_from_expr(expr: &Expr) -> Option<PropName> {
1025+
match expr {
1026+
Expr::Lit(e) => match &e {
1027+
Lit::Str(e) => Some(PropName::Str(e.clone())),
1028+
Lit::Num(e) => Some(PropName::Num(e.clone())),
1029+
Lit::BigInt(e) => Some(PropName::BigInt(e.clone())),
1030+
Lit::Bool(_) | Lit::Null(_) | Lit::Regex(_) | Lit::JSXText(_) => None,
1031+
},
1032+
Expr::Tpl(e) => {
1033+
if e.quasis.is_empty() && e.exprs.len() == 1 {
1034+
prop_name_from_expr(&e.exprs[0])
1035+
} else {
1036+
None
1037+
}
1038+
}
1039+
Expr::Paren(e) => prop_name_from_expr(&e.expr),
1040+
Expr::TsTypeAssertion(e) => prop_name_from_expr(&e.expr),
1041+
Expr::TsConstAssertion(e) => prop_name_from_expr(&e.expr),
1042+
Expr::TsNonNull(e) => prop_name_from_expr(&e.expr),
1043+
Expr::TsAs(e) => prop_name_from_expr(&e.expr),
1044+
Expr::TsSatisfies(e) => prop_name_from_expr(&e.expr),
1045+
Expr::Ident(_) => Some(PropName::Computed(ComputedPropName {
1046+
span: expr.span(),
1047+
expr: Box::new(expr.clone()),
1048+
})),
1049+
Expr::TaggedTpl(_)
1050+
| Expr::This(_)
1051+
| Expr::Array(_)
1052+
| Expr::Object(_)
1053+
| Expr::Fn(_)
1054+
| Expr::Unary(_)
1055+
| Expr::Update(_)
1056+
| Expr::Bin(_)
1057+
| Expr::Assign(_)
1058+
| Expr::Member(_)
1059+
| Expr::SuperProp(_)
1060+
| Expr::Cond(_)
1061+
| Expr::Call(_)
1062+
| Expr::New(_)
1063+
| Expr::Seq(_)
1064+
| Expr::Arrow(_)
1065+
| Expr::Class(_)
1066+
| Expr::Yield(_)
1067+
| Expr::Await(_)
1068+
| Expr::MetaProp(_)
1069+
| Expr::JSXMember(_)
1070+
| Expr::JSXNamespacedName(_)
1071+
| Expr::JSXEmpty(_)
1072+
| Expr::JSXElement(_)
1073+
| Expr::JSXFragment(_)
1074+
| Expr::TsInstantiation(_)
1075+
| Expr::PrivateName(_)
1076+
| Expr::OptChain(_)
1077+
| Expr::Invalid(_) => None,
1078+
}
1079+
}
1080+
1081+
match prop_name {
1082+
PropName::Ident(_) | PropName::Str(_) | PropName::Num(_) | PropName::BigInt(_) => {
1083+
Some(prop_name.clone())
1084+
}
1085+
PropName::Computed(computed) => prop_name_from_expr(&computed.expr),
1086+
}
1087+
}

‎crates/swc_typescript/tests/fast_dts_deno.rs

+91-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use swc_ecma_ast::EsVersion;
44
use swc_ecma_codegen::to_code;
5-
use swc_ecma_parser::{parse_file_as_module, Syntax, TsSyntax};
5+
use swc_ecma_parser::{parse_file_as_program, Syntax, TsSyntax};
66
use swc_typescript::fast_dts::FastDts;
77

88
#[track_caller]
@@ -15,7 +15,7 @@ fn transform_dts_test(source: &str, expected: &str) {
1515

1616
let mut checker = FastDts::new(fm.name.clone());
1717

18-
let mut module = parse_file_as_module(
18+
let mut program = parse_file_as_program(
1919
&fm,
2020
Syntax::Typescript(TsSyntax {
2121
..Default::default()
@@ -26,9 +26,9 @@ fn transform_dts_test(source: &str, expected: &str) {
2626
)
2727
.unwrap();
2828

29-
let _issues = checker.transform(&mut module);
29+
let _issues = checker.transform(&mut program);
3030

31-
let code = to_code(&module);
31+
let code = to_code(&program);
3232

3333
assert_eq!(
3434
code.trim(),
@@ -183,6 +183,32 @@ fn dts_class_decl_overloads_test() {
183183
foo(arg: number);
184184
}"#,
185185
);
186+
187+
transform_dts_test(
188+
r#"export abstract class Value {
189+
protected body?(): string | undefined | Promise<string | undefined>;
190+
protected footer(): string | undefined {
191+
return "";
192+
}
193+
}
194+
function overloadsNonExportDecl(args: string): void;
195+
function overloadsNonExportDecl(args: number): void;
196+
function overloadsNonExportDecl(args: any): void {}
197+
export { overloadsNonExportDecl };
198+
export default function defaultExport(args: string): void;
199+
export default function defaultExport(args: number): void;
200+
export default function defaultExport(args: any): void {}
201+
"#,
202+
r#"export declare abstract class Value {
203+
protected body?(): string | undefined | Promise<string | undefined>;
204+
protected footer(): string | undefined;
205+
}
206+
declare function overloadsNonExportDecl(args: string): void;
207+
declare function overloadsNonExportDecl(args: number): void;
208+
export { overloadsNonExportDecl };
209+
export default function defaultExport(args: string): void;
210+
export default function defaultExport(args: number): void;"#,
211+
);
186212
}
187213

188214
#[test]
@@ -238,6 +264,67 @@ fn dts_class_abstract_method_test() {
238264
);
239265
}
240266

267+
#[test]
268+
fn dts_class_params_initializers_test() {
269+
transform_dts_test(
270+
r#"export class Object {
271+
constructor(
272+
values: {},
273+
{
274+
a,
275+
b,
276+
}: {
277+
a?: A;
278+
b?: B;
279+
} = {}
280+
) {}
281+
282+
method(
283+
values: {},
284+
{
285+
a,
286+
b,
287+
}: {
288+
a?: A;
289+
b?: B;
290+
} = {},
291+
value = 1
292+
) {}
293+
}
294+
"#,
295+
r#"export declare class Object {
296+
constructor(values: {
297+
}, { a, b }?: {
298+
a?: A;
299+
b?: B;
300+
});
301+
method(values: {
302+
}, { a, b }?: {
303+
a?: A;
304+
b?: B;
305+
}, value?: number);
306+
}"#,
307+
);
308+
}
309+
310+
#[test]
311+
fn dts_class_properties_computed_test() {
312+
transform_dts_test(
313+
r#"export class Test {
314+
[Symbol.for("nodejs.util.inspect.custom")]() {
315+
}
316+
["string"]: string;
317+
["string2" as string]: string;
318+
[1 as number]: string;
319+
}"#,
320+
r#"export declare class Test {
321+
"string": string;
322+
"string2": string;
323+
1: string;
324+
}"#,
325+
);
326+
}
327+
241328
#[test]
242329
fn dts_var_decl_test() {
243330
transform_dts_test(

0 commit comments

Comments
 (0)
Please sign in to comment.