Skip to content

Commit b749373

Browse files
committed
fix(codegen): correctly parenthesise TSArrayType (#19784)
1 parent 876dc1b commit b749373

File tree

2 files changed

+48
-8
lines changed

2 files changed

+48
-8
lines changed

crates/oxc_codegen/src/gen.rs

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3094,7 +3094,9 @@ impl Gen for TSType<'_> {
30943094

30953095
impl Gen for TSArrayType<'_> {
30963096
fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3097-
self.element_type.print(p, ctx);
3097+
p.wrap(parenthesize_check_type_of_postfix_type(&self.element_type), |p| {
3098+
self.element_type.print(p, ctx);
3099+
});
30983100
p.print_str("[]");
30993101
}
31003102
}
@@ -3107,10 +3109,30 @@ impl Gen for TSTupleType<'_> {
31073109
}
31083110
}
31093111

3110-
fn parenthesize_check_type_of_conditional_type(ty: &TSType<'_>) -> bool {
3112+
fn parenthesize_check_type_of_union_type(ty: &TSType<'_>) -> bool {
31113113
matches!(
31123114
ty,
3113-
TSType::TSFunctionType(_) | TSType::TSConstructorType(_) | TSType::TSConditionalType(_)
3115+
TSType::TSFunctionType(_)
3116+
| TSType::TSConstructorType(_)
3117+
| TSType::TSConditionalType(_)
3118+
| TSType::TSInferType(_)
3119+
)
3120+
}
3121+
3122+
fn parenthesize_check_type_of_intersection_type(ty: &TSType<'_>) -> bool {
3123+
matches!(ty, TSType::TSUnionType(_)) || parenthesize_check_type_of_union_type(ty)
3124+
}
3125+
3126+
fn parenthesize_check_type_of_postfix_type(ty: &TSType<'_>) -> bool {
3127+
matches!(
3128+
ty,
3129+
TSType::TSUnionType(_)
3130+
| TSType::TSIntersectionType(_)
3131+
| TSType::TSFunctionType(_)
3132+
| TSType::TSConstructorType(_)
3133+
| TSType::TSConditionalType(_)
3134+
| TSType::TSInferType(_)
3135+
| TSType::TSTypeOperatorType(_)
31143136
)
31153137
}
31163138

@@ -3119,14 +3141,14 @@ impl Gen for TSUnionType<'_> {
31193141
let Some((first, rest)) = self.types.split_first() else {
31203142
return;
31213143
};
3122-
p.wrap(parenthesize_check_type_of_conditional_type(first), |p| {
3144+
p.wrap(parenthesize_check_type_of_union_type(first), |p| {
31233145
first.print(p, ctx);
31243146
});
31253147
for item in rest {
31263148
p.print_soft_space();
31273149
p.print_ascii_byte(b'|');
31283150
p.print_soft_space();
3129-
p.wrap(parenthesize_check_type_of_conditional_type(item), |p| {
3151+
p.wrap(parenthesize_check_type_of_union_type(item), |p| {
31303152
item.print(p, ctx);
31313153
});
31323154
}
@@ -3146,12 +3168,16 @@ impl Gen for TSIntersectionType<'_> {
31463168
let Some((first, rest)) = self.types.split_first() else {
31473169
return;
31483170
};
3149-
first.print(p, ctx);
3171+
p.wrap(parenthesize_check_type_of_intersection_type(first), |p| {
3172+
first.print(p, ctx);
3173+
});
31503174
for item in rest {
31513175
p.print_soft_space();
31523176
p.print_ascii_byte(b'&');
31533177
p.print_soft_space();
3154-
item.print(p, ctx);
3178+
p.wrap(parenthesize_check_type_of_intersection_type(item), |p| {
3179+
item.print(p, ctx);
3180+
});
31553181
}
31563182
}
31573183
}
@@ -3177,7 +3203,9 @@ impl Gen for TSInferType<'_> {
31773203

31783204
impl Gen for TSIndexedAccessType<'_> {
31793205
fn r#gen(&self, p: &mut Codegen, ctx: Context) {
3180-
self.object_type.print(p, ctx);
3206+
p.wrap(parenthesize_check_type_of_postfix_type(&self.object_type), |p| {
3207+
self.object_type.print(p, ctx);
3208+
});
31813209
p.print_ascii_byte(b'[');
31823210
self.index_type.print(p, ctx);
31833211
p.print_ascii_byte(b']');

crates/oxc_codegen/tests/integration/ts.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,18 @@ fn cases() {
1010
test_same("({ foo(): string {} });\n");
1111
test_same("({ method(this: Foo): void {} });\n");
1212
test_same("({ methodWithParam(this: Foo, bar: string): void {} });\n");
13+
test_same("type T = (A | B)[];\n");
14+
test_same("type T = (A & B)[];\n");
15+
test_same("type T = (keyof A)[];\n");
16+
test_same("type T = (() => A)[];\n");
17+
test_same("type T = (new () => A)[];\n");
18+
test_same("type T = (A extends B ? C : D)[];\n");
19+
test_same("type T = (A | B)[K];\n");
20+
test_same("type T = (A & B)[K];\n");
21+
test_same("type T = (keyof A)[K];\n");
22+
test_same("type T = (A extends B ? C : D)[K];\n");
23+
test_same("type T = A & (B extends C ? D : E);\n");
24+
test_same("type T = (A | B) & C;\n");
1325
test_same("interface I<in out T,> {}\n");
1426
test_same("function F<const in out T,>() {}\n");
1527
test_same("class C {\n\tp = await(0);\n}\n");

0 commit comments

Comments
 (0)