diff --git a/changelog_unreleased/typescript/12390.md b/changelog_unreleased/typescript/12390.md new file mode 100644 index 000000000..21be549b9 --- /dev/null +++ b/changelog_unreleased/typescript/12390.md @@ -0,0 +1,45 @@ +#### Print trailing comma for rest elements in tuple types (#12390 by @sosukesuzuki) + +TypeScript allows to put rest elements in places other than the end of tuple types since [4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html#leadingmiddle-rest-elements-in-tuple-types). +Prettier now prints a trailing comma for the trailing rest element as the it may be followed by the next element. + + +```tsx +// { trailingCommma: "all" } + +// Input +type Foo = [ + Element, + Element, + Element, + Element, + Element, + Element, + ...RestElement, +]; + + +// Prettier stable +type Foo = [ + Element, + Element, + Element, + Element, + Element, + Element, + ...RestElement +]; + + +// Prettier main +type Foo = [ + Element, + Element, + Element, + Element, + Element, + Element, + ...RestElement, +]; + +``` diff --git a/src/language-js/print/type-annotation.js b/src/language-js/print/type-annotation.js index 88f4c78cf..6b8ad87f7 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, isNonEmptyArray } = require("../../common/util.js"); +const { isNonEmptyArray } = require("../../common/util.js"); const { builders: { group, join, line, softline, indent, align, ifBreak }, } = require("../../document/index.js"); @@ -289,7 +289,6 @@ function printTupleType(path, options, print) { const typesField = node.type === "TSTupleType" ? "elementTypes" : "types"; const types = node[typesField]; const isNonEmptyTuple = isNonEmptyArray(types); - const hasRest = isNonEmptyTuple && getLast(types).type === "TSRestType"; const bracketsDelimiterLine = isNonEmptyTuple ? softline : ""; return group([ "[", @@ -297,9 +296,7 @@ function printTupleType(path, options, print) { bracketsDelimiterLine, printArrayItems(path, options, typesField, print), ]), - ifBreak( - isNonEmptyTuple && shouldPrintComma(options, "all") && !hasRest ? "," : "" - ), + ifBreak(isNonEmptyTuple && shouldPrintComma(options, "all") ? "," : ""), printDanglingComments(path, options, /* sameIndent */ true), bracketsDelimiterLine, "]", diff --git a/tests/format/typescript/tuple/__snapshots__/jsfmt.spec.js.snap b/tests/format/typescript/tuple/__snapshots__/jsfmt.spec.js.snap index e2c610475..3f38b0853 100644 --- a/tests/format/typescript/tuple/__snapshots__/jsfmt.spec.js.snap +++ b/tests/format/typescript/tuple/__snapshots__/jsfmt.spec.js.snap @@ -1,91 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`no-trailing-comma-after-rest.ts - {"trailingComma":"all"} format 1`] = ` -====================================options===================================== -parsers: ["typescript"] -printWidth: 80 -trailingComma: "all" - | printWidth -=====================================input====================================== -type ValidateArgs = [ - { - [key: string]: any; - }, - string, - string, - ...string[], -]; - -=====================================output===================================== -type ValidateArgs = [ - { - [key: string]: any; - }, - string, - string, - ...string[] -]; - -================================================================================ -`; - -exports[`no-trailing-comma-after-rest.ts - {"trailingComma":"none"} format 1`] = ` -====================================options===================================== -parsers: ["typescript"] -printWidth: 80 -trailingComma: "none" - | printWidth -=====================================input====================================== -type ValidateArgs = [ - { - [key: string]: any; - }, - string, - string, - ...string[], -]; - -=====================================output===================================== -type ValidateArgs = [ - { - [key: string]: any; - }, - string, - string, - ...string[] -]; - -================================================================================ -`; - -exports[`no-trailing-comma-after-rest.ts format 1`] = ` -====================================options===================================== -parsers: ["typescript"] -printWidth: 80 - | printWidth -=====================================input====================================== -type ValidateArgs = [ - { - [key: string]: any; - }, - string, - string, - ...string[], -]; - -=====================================output===================================== -type ValidateArgs = [ - { - [key: string]: any; - }, - string, - string, - ...string[] -]; - -================================================================================ -`; - exports[`trailing-comma.ts - {"trailingComma":"all"} format 1`] = ` ====================================options===================================== parsers: ["typescript"] @@ -273,6 +187,92 @@ type Foo = ================================================================================ `; +exports[`trailing-comma-trailing-rest.ts - {"trailingComma":"all"} format 1`] = ` +====================================options===================================== +parsers: ["typescript"] +printWidth: 80 +trailingComma: "all" + | printWidth +=====================================input====================================== +type ValidateArgs = [ + { + [key: string]: any; + }, + string, + string, + ...string[], +]; + +=====================================output===================================== +type ValidateArgs = [ + { + [key: string]: any; + }, + string, + string, + ...string[], +]; + +================================================================================ +`; + +exports[`trailing-comma-trailing-rest.ts - {"trailingComma":"none"} format 1`] = ` +====================================options===================================== +parsers: ["typescript"] +printWidth: 80 +trailingComma: "none" + | printWidth +=====================================input====================================== +type ValidateArgs = [ + { + [key: string]: any; + }, + string, + string, + ...string[], +]; + +=====================================output===================================== +type ValidateArgs = [ + { + [key: string]: any; + }, + string, + string, + ...string[] +]; + +================================================================================ +`; + +exports[`trailing-comma-trailing-rest.ts format 1`] = ` +====================================options===================================== +parsers: ["typescript"] +printWidth: 80 + | printWidth +=====================================input====================================== +type ValidateArgs = [ + { + [key: string]: any; + }, + string, + string, + ...string[], +]; + +=====================================output===================================== +type ValidateArgs = [ + { + [key: string]: any; + }, + string, + string, + ...string[] +]; + +================================================================================ +`; + exports[`tuple.ts - {"trailingComma":"all"} format 1`] = ` ====================================options===================================== parsers: ["typescript"] diff --git a/tests/format/typescript/tuple/no-trailing-comma-after-rest.ts b/tests/format/typescript/tuple/trailing-comma-trailing-rest.ts similarity index 100% rename from tests/format/typescript/tuple/no-trailing-comma-after-rest.ts rename to tests/format/typescript/tuple/trailing-comma-trailing-rest.ts