diff --git a/changelog_unreleased/typescript/11884.md b/changelog_unreleased/typescript/11884.md new file mode 100644 index 000000000..a2cdcfbb9 --- /dev/null +++ b/changelog_unreleased/typescript/11884.md @@ -0,0 +1,32 @@ +#### Improve formatting for empty tuple types (#11884 by @sosukesuzuki) + + +```tsx +// Input +type Foo = + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooo extends [] + ? Foo3 + : Foo4; + +// Prettier stable +type Foo = Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooo extends [ + +] + ? Foo3 + : Foo4; + +// Prettier stable (tailingCommma = all) +// Invalid TypeScript code +type Foo = Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooo extends [ + , +] + ? Foo3 + : Foo4; + +// Prettier main +type Foo = + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooo extends [] + ? Foo3 + : Foo4; + +``` diff --git a/src/language-js/print/type-annotation.js b/src/language-js/print/type-annotation.js index 7772e9099..c1e2d6497 100644 --- a/src/language-js/print/type-annotation.js +++ b/src/language-js/print/type-annotation.js @@ -4,7 +4,7 @@ const { printComments, printDanglingComments, } = require("../../main/comments.js"); -const { getLast } = require("../../common/util.js"); +const { getLast, isNonEmptyArray } = require("../../common/util.js"); const { builders: { group, join, line, softline, indent, align, ifBreak }, } = require("../../document/index.js"); @@ -287,15 +287,21 @@ function printFunctionType(path, options, print) { function printTupleType(path, options, print) { const node = path.getValue(); const typesField = node.type === "TSTupleType" ? "elementTypes" : "types"; - const hasRest = - node[typesField].length > 0 && - getLast(node[typesField]).type === "TSRestType"; + const types = node[typesField]; + const isNonEmptyTuple = isNonEmptyArray(types); + const hasRest = isNonEmptyTuple && getLast(types).type === "TSRestType"; + const bracketsDelimiterLine = isNonEmptyTuple ? softline : ""; return group([ "[", - indent([softline, printArrayItems(path, options, typesField, print)]), - ifBreak(shouldPrintComma(options, "all") && !hasRest ? "," : ""), + indent([ + bracketsDelimiterLine, + printArrayItems(path, options, typesField, print), + ]), + ifBreak( + isNonEmptyTuple && shouldPrintComma(options, "all") && !hasRest ? "," : "" + ), printDanglingComments(path, options, /* sameIndent */ true), - softline, + bracketsDelimiterLine, "]", ]); } diff --git a/tests/format/typescript/tuple/__snapshots__/jsfmt.spec.js.snap b/tests/format/typescript/tuple/__snapshots__/jsfmt.spec.js.snap index 9681ac3ce..e2c610475 100644 --- a/tests/format/typescript/tuple/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/typescript/tuple/__snapshots__/jsfmt.spec.js.snap @@ -208,6 +208,71 @@ export interface ShopQueryResult { ================================================================================ `; +exports[`trailing-comma-for-empty-tuples.ts - {"trailingComma":"all"} format 1`] = ` +====================================options===================================== +parsers: ["typescript"] +printWidth: 80 +trailingComma: "all" + | printWidth +=====================================input====================================== +type Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong = [] + +type Foo = Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooo extends [] ? Foo3 : Foo4; +=====================================output===================================== +type Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong = + []; + +type Foo = + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooo extends [] + ? Foo3 + : Foo4; + +================================================================================ +`; + +exports[`trailing-comma-for-empty-tuples.ts - {"trailingComma":"none"} format 1`] = ` +====================================options===================================== +parsers: ["typescript"] +printWidth: 80 +trailingComma: "none" + | printWidth +=====================================input====================================== +type Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong = [] + +type Foo = Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooo extends [] ? Foo3 : Foo4; +=====================================output===================================== +type Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong = + []; + +type Foo = + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooo extends [] + ? Foo3 + : Foo4; + +================================================================================ +`; + +exports[`trailing-comma-for-empty-tuples.ts format 1`] = ` +====================================options===================================== +parsers: ["typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +type Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong = [] + +type Foo = Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooo extends [] ? Foo3 : Foo4; +=====================================output===================================== +type Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong = + []; + +type Foo = + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooo extends [] + ? Foo3 + : Foo4; + +================================================================================ +`; + exports[`tuple.ts - {"trailingComma":"all"} format 1`] = ` ====================================options===================================== parsers: ["typescript"] diff --git a/tests/format/typescript/tuple/trailing-comma-for-empty-tuples.ts b/tests/format/typescript/tuple/trailing-comma-for-empty-tuples.ts new file mode 100644 index 000000000..5c1b15725 --- /dev/null +++ b/tests/format/typescript/tuple/trailing-comma-for-empty-tuples.ts @@ -0,0 +1,3 @@ +type Loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong = [] + +type Foo = Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooo extends [] ? Foo3 : Foo4; \ No newline at end of file