Repository: prettier/prettier (JavaScript)

Issue:
Prettier removes trailing comma from multiline type with `trailingComma: all`
**Prettier 2.5.1**
[Playground link](https://prettier.io/playground/#N4Igxg9gdgLgprEAuEMCeAHOACAYgSwCcBnGAFUzgHV8YALANTkLQBloBzAOQEMBbHAF5swADpRs2HkmxQArnwBGzANziAvuPHos2AMpxIUACYUsNekxbso3fkJHjJimfKWqNW2JTz4oPABszalpGZjZOXgFsYQBtJ18SckoLMOtI+wAaBIA6PIMjUxTQqwjbKLhYgF1sqCqVEEyQCAwYfGhiZFAeQkIIAHcABR6ETpRA-p40TqbFQh4wAGs4GD17Vj84ZAAzQOI4Wfmllb0MBb8OZBhCOQOQOHdjYzhjVh5bOR4OOFwIQj4eDA2rZkCAeHIYBBGiA6DA+AEqHRaHBiGcwHADFBiLR8AA3WhoUFgYgzEB+faEGCDeYcAE7PZ3ABWxAAHnoLgE4ABFOQQeD0gL7JpnEjMUE6FFgQj4VrQjDS2A0Yz0ZAADgADMK+vsqPMMKD5SjmLitk0AI68+DUlpjMHEAC0UDgLxe0MIcAtRDg1K+dKQu0Fd32fHwVxuQY53MtW39DKaMB4iiVKqQACZ4-N8AELgBhCB8P1ggIBaFyfZkRNjANCkC424ASRMCFWUplMAAgiY9OhOQL9up1EA)

```sh
# Options:
--parser typescript
--trailingComma all
```

**Input:**

```jsx
type FirstTypeWithVeryLongName = {
  a: number;
}

type SecondTypeWithVeryLongName = {
  b: number;
}

type FinalTypeWithVeryLongName = [
  FirstTypeWithVeryLongName,
  ...SecondTypeWithVeryLongName[],
];
```

**Output:**

```jsx
type FirstTypeWithVeryLongName = {
  a: number;
};

type SecondTypeWithVeryLongName = {
  b: number;
};

type FinalTypeWithVeryLongName = [
  FirstTypeWithVeryLongName,
  ...SecondTypeWithVeryLongName[]
];
```

**Expected behavior:**
Prettier doesn't remove trailing comma from `FinalTypeWithVeryLongName` after `...SecondTypeWithVeryLongName[]` and thus doesn't conflict with `@typescript-eslint/comma-dangle` rule.


Hints:
https://github.com/prettier/prettier/issues/11684
It's also reproduced
This is a remnant of the old TS spec of placing rest elements only at the end of a tuple. I think we can fix this.
We can put leading/middle rest type in tuples types since TypeScript 4.2 https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html#leadingmiddle-rest-elements-in-tuple-types

Patch:
diff --git a/src/language-js/print/type-annotation.js b/src/language-js/print/type-annotation.js
--- 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,
     "]",


Test patch:
diff --git a/tests/format/typescript/tuple/__snapshots__/jsfmt.spec.js.snap b/tests/format/typescript/tuple/__snapshots__/jsfmt.spec.js.snap
--- 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