fix(codegen): preserve cast parentheses in conditional tests (#25115)

## Summary

- preserve parentheses around as and satisfies expressions used as conditional tests
- prevent a following regular expression consequent from being parsed as part of the type expression
- add regression coverage for both TypeScript expression forms

Part of #25111.
Closes #25114.
This commit is contained in:
camc314 committed 2026-08-09 12:26:21 +00:00
1 parent 8b7d4419ef
commit d07a293d12
2 files changed
+18 -1

No files matched your search

+12 -1
View File
@@ -2029,7 +2029,18 @@ impl GenExpr for ConditionalExpression<'_> {
ctx &= Context::FORBID_IN.not();
}
p.wrap(wrap, |p| {
self.test.print_expr(p, Precedence::Conditional, ctx & Context::FORBID_IN);
// Keep `as` and `satisfies` expressions grouped as the conditional test. Without
// parentheses, a regexp consequent such as `(value as Type) ? /x/ : y` fails to
// reparse.
let test_precedence = if matches!(
self.test.without_parentheses(),
Expression::TSAsExpression(_) | Expression::TSSatisfiesExpression(_)
) {
Precedence::Compare
} else {
Precedence::Conditional
};
self.test.print_expr(p, test_precedence, ctx & Context::FORBID_IN);
p.print_soft_space();
p.print_ascii_byte(b'?');
p.print_soft_space();
@@ -358,6 +358,12 @@ fn ts_as_expression_in_binary_expr() {
);
}
#[test]
fn ts_cast_expression_in_conditional_test() {
test_same("let a = typeof ((\"a\" as unknown) ? /a/ : false);\n");
test_same("let a = typeof ((\"a\" satisfies foo) ? /a/ : false);\n");
}
#[test]
fn ts_type_assertion() {
// `<T>x` (TS angle-bracket assertion) is only valid in non-tsx source.