From 2d556cbb2eca7999d40069649cef0d26c797d9be Mon Sep 17 00:00:00 2001 From: Dunqing <29533304+Dunqing@users.noreply.github.com> Date: Mon, 22 Dec 2025 09:46:14 +0000 Subject: [PATCH] fix(formatter): should treat TSMappedType as a complex type in assignment-like formatting (#17257) Part of #16956 --- .../src/utils/assignment_like.rs | 8 +++- .../ts/assignments/complex-type-arguments.ts | 9 ++++ .../complex-type-arguments.ts.snap | 42 +++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 crates/oxc_formatter/tests/fixtures/ts/assignments/complex-type-arguments.ts create mode 100644 crates/oxc_formatter/tests/fixtures/ts/assignments/complex-type-arguments.ts.snap diff --git a/crates/oxc_formatter/src/utils/assignment_like.rs b/crates/oxc_formatter/src/utils/assignment_like.rs index b9e4ac0befa81..9e43d636d7b76 100644 --- a/crates/oxc_formatter/src/utils/assignment_like.rs +++ b/crates/oxc_formatter/src/utils/assignment_like.rs @@ -994,7 +994,13 @@ fn is_complex_type_arguments(type_arguments: &TSTypeParameterInstantiation) -> b let is_first_argument_complex = ts_type_argument_list.first().is_some_and(|first_argument| { matches!( first_argument, - TSType::TSUnionType(_) | TSType::TSIntersectionType(_) | TSType::TSTypeLiteral(_) + TSType::TSUnionType(_) + | TSType::TSIntersectionType(_) + | TSType::TSTypeLiteral(_) + // TODO: This is not part of Prettier's logic, but it makes sense to consider mapped types as + // complex because it is the same as type literals in terms of structure. + // NOTE: Once the `will_break` logic is added, this will have to be revisited. + | TSType::TSMappedType(_) ) }); diff --git a/crates/oxc_formatter/tests/fixtures/ts/assignments/complex-type-arguments.ts b/crates/oxc_formatter/tests/fixtures/ts/assignments/complex-type-arguments.ts new file mode 100644 index 0000000000000..6273db8985a3d --- /dev/null +++ b/crates/oxc_formatter/tests/fixtures/ts/assignments/complex-type-arguments.ts @@ -0,0 +1,9 @@ +// Type argument is a `TSMappedType` +const emitter = createGlobalEmitter<{ + [key in Event["type"]]: Extract +}>() + +// Type argument is a `TSTypeLiteral` +const emitter2 = createGlobalEmitter<{ + longlonglonglongKey: Extract +}>() diff --git a/crates/oxc_formatter/tests/fixtures/ts/assignments/complex-type-arguments.ts.snap b/crates/oxc_formatter/tests/fixtures/ts/assignments/complex-type-arguments.ts.snap new file mode 100644 index 0000000000000..0e1a05c7a89c5 --- /dev/null +++ b/crates/oxc_formatter/tests/fixtures/ts/assignments/complex-type-arguments.ts.snap @@ -0,0 +1,42 @@ +--- +source: crates/oxc_formatter/tests/fixtures/mod.rs +--- +==================== Input ==================== +// Type argument is a `TSMappedType` +const emitter = createGlobalEmitter<{ + [key in Event["type"]]: Extract +}>() + +// Type argument is a `TSTypeLiteral` +const emitter2 = createGlobalEmitter<{ + longlonglonglongKey: Extract +}>() + +==================== Output ==================== +------------------ +{ printWidth: 80 } +------------------ +// Type argument is a `TSMappedType` +const emitter = createGlobalEmitter<{ + [key in Event["type"]]: Extract; +}>(); + +// Type argument is a `TSTypeLiteral` +const emitter2 = createGlobalEmitter<{ + longlonglonglongKey: Extract; +}>(); + +------------------- +{ printWidth: 100 } +------------------- +// Type argument is a `TSMappedType` +const emitter = createGlobalEmitter<{ + [key in Event["type"]]: Extract; +}>(); + +// Type argument is a `TSTypeLiteral` +const emitter2 = createGlobalEmitter<{ + longlonglonglongKey: Extract; +}>(); + +===================== End =====================