Repository: prettier/prettier (JavaScript)

Issue:
Nested TypeScript generics are not well line-wrapped (even if input is)
Found a bug. Thank you for your consideration!

**Prettier 2.8.7**
[Playground link](https://prettier.io/playground/#N4Igxg9gdgLgprEAuEcAeAHCAnGACGATwzjwHkBXebAFWLgB4AdKPPAGWgHM5tOoefbr36CAklCi86JPOnhQAJgGcOwoQJHrRvMjAAW0+s1ZtyUgLI44MuCzYA+Fg7wBePMACGSPAEYAvgDcLAD0IXgACthwMDAAlrx4EFQYVHhxqgA26gT6nqwAHAAMeGB52J5g1MogADQgEBjx0DVIoJ7Y2BAA7hEdCK0gnpndnoQ19QBGFWAA1jEAyp4AtnDscVLIAGbDynBTM-MwCxiVG1zIMNgU+6jLk3CKio-s+VwUnjwAYjjLnrHnZBDKgQOogfQwZaZADq+ji8GUpzAcAWA3hcQAbvDCECwMoJiANntcFFPn9trtbgArZRoBbnTJwACKFAg8ApmT29VO2GJQKIJGUYGwcSaYIwItg0LiigMyGK3K6e2hFQwQIlcGJGLgYIAjqz4FFGoNPMoALRSR6PMHRfVxaKkrjkpA7Tm3PbLOKXa7uhlwACCsRFkyocAiIg2OpdlPqyj9LLZUddXJAME8k2lsv0yAATPUrp44plzgBhCDLZ2oZQAVjBFD2NHTrWTtwxNwkz1gC2Fopg-qUCyIjI5e38-iAA)
<!-- prettier-ignore -->
```sh
--parser typescript
```

**Input:**
<!-- prettier-ignore -->
```tsx
export type OuterType<
  LongerLongerLongerLongerInnerType extends LongerLongerLongerLongerOtherType<
    OneMoreType
  >
> = {a: 1};
// Prettier output is longer than 80 characters
```

**Output:**
<!-- prettier-ignore -->
```tsx
export type OuterType<
  LongerLongerLongerLongerInnerType extends LongerLongerLongerLongerOtherType<OneMoreType>
> = { a: 1 };
// Prettier output is longer than 80 characters
```

**Expected behavior:**
I expect the Prettier output to fit within the 80 character line length (especially since the input does)


Hints:
(I tried commenting things like #11923 but that didn't work. Having to resort to `// prettier-ignore` for now)
I prefer breaking line after `extends` for this case:

```ts
export type OuterType<
  LongerLongerLongerLongerInnerType extends
  　　LongerLongerLongerLongerOtherType<OneMoreType>
> = {a: 1};
```

Patch:
diff --git a/src/language-js/print/type-parameters.js b/src/language-js/print/type-parameters.js
--- a/src/language-js/print/type-parameters.js
+++ b/src/language-js/print/type-parameters.js
@@ -112,6 +112,10 @@ function printDanglingCommentsForInline(path, options) {
 
 function printTypeParameter(path, options, print) {
   const { node, parent } = path;
+
+  /**
+   * @type {import("../../document/builders.js").Doc[]}
+   */
   const parts = [node.type === "TSTypeParameter" && node.const ? "const " : ""];
 
   const name = node.type === "TSTypeParameter" ? print("name") : node.name;
@@ -160,14 +164,14 @@ function printTypeParameter(path, options, print) {
   }
 
   if (node.constraint) {
-    parts.push(" extends ", print("constraint"));
+    parts.push(" extends", indent([line, print("constraint")]));
   }
 
   if (node.default) {
     parts.push(" = ", print("default"));
   }
 
-  return parts;
+  return group(parts);
 }
 
 export { printTypeParameter, printTypeParameters, getTypeParametersGroupId };


Test patch:
diff --git a/tests/format/typescript/typeparams/__snapshots__/jsfmt.spec.js.snap b/tests/format/typescript/typeparams/__snapshots__/jsfmt.spec.js.snap
--- a/tests/format/typescript/typeparams/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/format/typescript/typeparams/__snapshots__/jsfmt.spec.js.snap
@@ -362,6 +362,54 @@ class _ {
 ================================================================================
 `;
 
+exports[`line-breaking-after-extends.ts format 1`] = `
+====================================options=====================================
+parsers: ["typescript"]
+printWidth: 80
+                                                                                | printWidth
+=====================================input======================================
+export type OuterType1<
+  LongerLongerLongerLongerInnerType extends LongerLongerLongerLongerOtherType<OneMoreType>
+> = { a: 1 };
+
+export type OuterType2<
+  LongerLongerLongerLongerInnerType extends LongerLongerLongerLongerLongerLongerLongerLongerOtherType
+> = { a: 1 };
+
+export type OuterType3<
+  LongerLongerLongerLongerInnerType extends LongerLongerLongerLongerLongerLo.ngerLongerLongerOtherType
+> = { a: 1 };
+
+export type OuterType4<
+  LongerLongerLongerLongerInnerType extends
+    | LongerLongerLongerLongerLongerLo
+    | ngerLongerLongerOtherType
+> = { a: 1 };
+
+=====================================output=====================================
+export type OuterType1<
+  LongerLongerLongerLongerInnerType extends
+    LongerLongerLongerLongerOtherType<OneMoreType>,
+> = { a: 1 };
+
+export type OuterType2<
+  LongerLongerLongerLongerInnerType extends
+    LongerLongerLongerLongerLongerLongerLongerLongerOtherType,
+> = { a: 1 };
+
+export type OuterType3<
+  LongerLongerLongerLongerInnerType extends
+    LongerLongerLongerLongerLongerLo.ngerLongerLongerOtherType,
+> = { a: 1 };
+
+export type OuterType4<
+  LongerLongerLongerLongerInnerType extends
+    LongerLongerLongerLongerLongerLo | ngerLongerLongerOtherType,
+> = { a: 1 };
+
+================================================================================
+`;
+
 exports[`long-function-arg.ts format 1`] = `
 ====================================options=====================================
 parsers: ["typescript"]
diff --git a/tests/format/typescript/typeparams/line-breaking-after-extends.ts b/tests/format/typescript/typeparams/line-breaking-after-extends.ts
new file mode 100644
--- /dev/null
+++ b/tests/format/typescript/typeparams/line-breaking-after-extends.ts
@@ -0,0 +1,17 @@
+export type OuterType1<
+  LongerLongerLongerLongerInnerType extends LongerLongerLongerLongerOtherType<OneMoreType>
+> = { a: 1 };
+
+export type OuterType2<
+  LongerLongerLongerLongerInnerType extends LongerLongerLongerLongerLongerLongerLongerLongerOtherType
+> = { a: 1 };
+
+export type OuterType3<
+  LongerLongerLongerLongerInnerType extends LongerLongerLongerLongerLongerLo.ngerLongerLongerOtherType
+> = { a: 1 };
+
+export type OuterType4<
+  LongerLongerLongerLongerInnerType extends
+    | LongerLongerLongerLongerLongerLo
+    | ngerLongerLongerOtherType
+> = { a: 1 };