From 96546f353faf9d103961344cdac6c60e20ecff35 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Fri, 30 Jan 2026 01:27:45 +0800 Subject: [PATCH] Fix printing comment for the last operand of union types (#18798) --- changelog_unreleased/typescript/18798.md | 40 +++++++++++++++++ src/language-js/comments/handle-comments.js | 15 ++++--- src/language-js/utilities/node-types.js | 5 +++ .../union/__snapshots__/format.test.js.snap | 31 ------------- .../union/__snapshots__/format.test.js.snap | 31 ------------- tests/format/typescript/union/comments.ts | 9 ---- .../__snapshots__/format.test.js.snap | 5 ++- .../__snapshots__/format.test.js.snap | 43 +++++++++++++++++++ .../union-last-comment.ts} | 5 +++ 9 files changed, 107 insertions(+), 77 deletions(-) create mode 100644 changelog_unreleased/typescript/18798.md delete mode 100644 tests/format/typescript/union/comments.ts rename tests/format/{flow/union/comments.js => typescript/union/consistent-with-flow/union-last-comment.ts} (66%) diff --git a/changelog_unreleased/typescript/18798.md b/changelog_unreleased/typescript/18798.md new file mode 100644 index 000000000..c178d9ed1 --- /dev/null +++ b/changelog_unreleased/typescript/18798.md @@ -0,0 +1,40 @@ +#### Fix printing comment for the last operand of union types (#18798 by @fisker) + + +```tsx +// Input +type Foo2 = ( + | "thing1" // Comment1 + | "thing2" // Comment2 +) & Bar; // Final comment2 +type Foo2 = ( + | "thing1" // Comment1 + | "thing2" // Comment2 +) | Bar; // Final comment2 + +// Prettier stable +type Foo2 = ( + | "thing1" // Comment1 + | "thing2" // Comment2 +) & + Bar; // Final comment2 +type Foo2 = + | ( + | "thing1" // Comment1 + | "thing2" + ) // Comment2 + | Bar; // Final comment2 + +// Prettier main +type Foo2 = ( + | "thing1" // Comment1 + | "thing2" // Comment2 +) & + Bar; // Final comment2 +type Foo2 = + | ( + | "thing1" // Comment1 + | "thing2" // Comment2 + ) + | Bar; // Final comment2 +``` diff --git a/src/language-js/comments/handle-comments.js b/src/language-js/comments/handle-comments.js index eabb4eb12..1014829f3 100644 --- a/src/language-js/comments/handle-comments.js +++ b/src/language-js/comments/handle-comments.js @@ -20,6 +20,7 @@ import { isObjectProperty } from "../utilities/is-object-property.js"; import { isPrettierIgnoreComment } from "../utilities/is-prettier-ignore-comment.js"; import { isTypeCastComment } from "../utilities/is-type-cast-comment.js"; import { + isArrayType, isBinaryCastExpression, isCallLikeExpression, isCallOrNewExpression, @@ -994,7 +995,7 @@ function handleSwitchDefaultCaseComments({ } /** - * Handle `Comment2` and `Comment4`. + * Handle `Comment2`, `Comment4`, `Comment6`. * * type Foo = ( * | "thing1" // Comment1 @@ -1006,6 +1007,11 @@ function handleSwitchDefaultCaseComments({ * | "thing2" // Comment4 * ) & Bar; * + * type Foo = ( + * | "thing1" // Comment5 + * | "thing2" // Comment6 + * ) | Bar; + * * @param {CommentContext} context * @returns {boolean} */ @@ -1017,10 +1023,9 @@ function handleLastUnionElementInExpression({ }) { if ( isUnionType(precedingNode) && - (((enclosingNode.type === "TSArrayType" || - enclosingNode.type === "ArrayTypeAnnotation") && - !followingNode) || - isIntersectionType(enclosingNode)) + ((isArrayType(enclosingNode) && !followingNode) || + isIntersectionType(enclosingNode) || + isUnionType(enclosingNode)) ) { addTrailingComment(precedingNode.types.at(-1), comment); return true; diff --git a/src/language-js/utilities/node-types.js b/src/language-js/utilities/node-types.js index d7ccb4043..f949ce663 100644 --- a/src/language-js/utilities/node-types.js +++ b/src/language-js/utilities/node-types.js @@ -132,4 +132,9 @@ export const isChainElementWrapper = createTypeCheckFunction([ "TSNonNullExpression", ]); +export const isArrayType = createTypeCheckFunction([ + "TSArrayType", + "ArrayTypeAnnotation", +]); + export * from "./literal.js"; diff --git a/tests/format/flow/union/__snapshots__/format.test.js.snap b/tests/format/flow/union/__snapshots__/format.test.js.snap index 0477e1338..f7e841398 100644 --- a/tests/format/flow/union/__snapshots__/format.test.js.snap +++ b/tests/format/flow/union/__snapshots__/format.test.js.snap @@ -22,37 +22,6 @@ const myValue = (callcallcallcallcallcall( ================================================================================ `; -exports[`comments.js format 1`] = ` -====================================options===================================== -parsers: ["flow"] -printWidth: 80 - | printWidth -=====================================input====================================== -type Foo = ( - | "thing1" // Comment1 - | "thing2" // Comment2 -)[]; // Final comment1 - -type Foo = ( - | "thing1" // Comment1 - | "thing2" // Comment2 -) & Bar; // Final comment2 - -=====================================output===================================== -type Foo = ( - | "thing1" // Comment1 - | "thing2" // Comment2 -)[]; // Final comment1 - -type Foo = ( - | "thing1" // Comment1 - | "thing2" // Comment2 -) & - Bar; // Final comment2 - -================================================================================ -`; - exports[`union.js format 1`] = ` ====================================options===================================== parsers: ["flow"] diff --git a/tests/format/typescript/union/__snapshots__/format.test.js.snap b/tests/format/typescript/union/__snapshots__/format.test.js.snap index b27a75512..034ff4698 100644 --- a/tests/format/typescript/union/__snapshots__/format.test.js.snap +++ b/tests/format/typescript/union/__snapshots__/format.test.js.snap @@ -1,36 +1,5 @@ // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing -exports[`comments.ts format 1`] = ` -====================================options===================================== -parsers: ["typescript"] -printWidth: 80 - | printWidth -=====================================input====================================== -type Foo = ( - | "thing1" // Comment1 - | "thing2" // Comment2 -)[]; // Final comment1 - -type Foo = ( - | "thing1" // Comment1 - | "thing2" // Comment2 -) & Bar; // Final comment2 - -=====================================output===================================== -type Foo = ( - | "thing1" // Comment1 - | "thing2" // Comment2 -)[]; // Final comment1 - -type Foo = ( - | "thing1" // Comment1 - | "thing2" // Comment2 -) & - Bar; // Final comment2 - -================================================================================ -`; - exports[`inlining.ts format 1`] = ` ====================================options===================================== parsers: ["typescript"] diff --git a/tests/format/typescript/union/comments.ts b/tests/format/typescript/union/comments.ts deleted file mode 100644 index fac6e0706..000000000 --- a/tests/format/typescript/union/comments.ts +++ /dev/null @@ -1,9 +0,0 @@ -type Foo = ( - | "thing1" // Comment1 - | "thing2" // Comment2 -)[]; // Final comment1 - -type Foo = ( - | "thing1" // Comment1 - | "thing2" // Comment2 -) & Bar; // Final comment2 diff --git a/tests/format/typescript/union/comments/__snapshots__/format.test.js.snap b/tests/format/typescript/union/comments/__snapshots__/format.test.js.snap index 83dc8a974..368b85eb2 100644 --- a/tests/format/typescript/union/comments/__snapshots__/format.test.js.snap +++ b/tests/format/typescript/union/comments/__snapshots__/format.test.js.snap @@ -208,7 +208,10 @@ type A2 = | c; type A4 = - | (A | B) // comment 1 + | ( + | A + | B // comment 1 + ) // comment2 | (A | B); diff --git a/tests/format/typescript/union/consistent-with-flow/__snapshots__/format.test.js.snap b/tests/format/typescript/union/consistent-with-flow/__snapshots__/format.test.js.snap index af3dbcd1f..821c437f3 100644 --- a/tests/format/typescript/union/consistent-with-flow/__snapshots__/format.test.js.snap +++ b/tests/format/typescript/union/consistent-with-flow/__snapshots__/format.test.js.snap @@ -380,6 +380,49 @@ type B2 = ================================================================================ `; +exports[`union-last-comment.ts format 1`] = ` +====================================options===================================== +parsers: ["typescript", "flow"] +printWidth: 80 + | printWidth +=====================================input====================================== +type Foo = ( + | "thing1" // Comment1 + | "thing2" // Comment2 +)[]; // Final comment1 + +type Foo = ( + | "thing1" // Comment1 + | "thing2" // Comment2 +) & Bar; // Final comment2 + +type Foo = ( + | "thing1" // Comment1 + | "thing2" // Comment2 +) | Bar; // Final comment2 + +=====================================output===================================== +type Foo = ( + | "thing1" // Comment1 + | "thing2" // Comment2 +)[]; // Final comment1 + +type Foo = ( + | "thing1" // Comment1 + | "thing2" // Comment2 +) & + Bar; // Final comment2 + +type Foo = + | ( + | "thing1" // Comment1 + | "thing2" // Comment2 + ) + | Bar; // Final comment2 + +================================================================================ +`; + exports[`within-tuple.ts format 1`] = ` ====================================options===================================== parsers: ["typescript", "flow"] diff --git a/tests/format/flow/union/comments.js b/tests/format/typescript/union/consistent-with-flow/union-last-comment.ts similarity index 66% rename from tests/format/flow/union/comments.js rename to tests/format/typescript/union/consistent-with-flow/union-last-comment.ts index fac6e0706..d2cee067f 100644 --- a/tests/format/flow/union/comments.js +++ b/tests/format/typescript/union/consistent-with-flow/union-last-comment.ts @@ -7,3 +7,8 @@ type Foo = ( | "thing1" // Comment1 | "thing2" // Comment2 ) & Bar; // Final comment2 + +type Foo = ( + | "thing1" // Comment1 + | "thing2" // Comment2 +) | Bar; // Final comment2