Skip to content

Commit bc18fa4

Browse files
authored
Fix incorrect removal of parentheses when using an infer with a constraint in a function predicate (#14279)
1 parent f602be5 commit bc18fa4

File tree

5 files changed

+106
-23
lines changed

5 files changed

+106
-23
lines changed

Diff for: changelog_unreleased/typescript/14279.md

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#### Fix parens in inferred function return types with `extends` (#14279 by @fisker)
2+
3+
<!-- prettier-ignore -->
4+
```ts
5+
// Input
6+
type Foo<T> = T extends ((a) => a is infer R extends string) ? R : never;
7+
8+
// Prettier stable (First format)
9+
type Foo<T> = T extends (a) => a is infer R extends string ? R : never;
10+
11+
// Prettier stable (Second format)
12+
SyntaxError: '?' expected.
13+
14+
// Prettier main
15+
type Foo<T> = T extends ((a) => a is infer R extends string) ? R : never;
16+
```

Diff for: src/language-js/needs-parens.js

+16-8
Original file line numberDiff line numberDiff line change
@@ -466,22 +466,30 @@ function needsParens(path, options) {
466466
}
467467

468468
case "TSConditionalType":
469-
if (name === "extendsType" && parent.type === "TSConditionalType") {
470-
return true;
471-
}
472-
// fallthrough
473469
case "TSFunctionType":
474470
case "TSConstructorType":
475471
if (name === "extendsType" && parent.type === "TSConditionalType") {
476-
const returnTypeAnnotation = (node.returnType || node.typeAnnotation)
477-
.typeAnnotation;
472+
if (node.type === "TSConditionalType") {
473+
return true;
474+
}
475+
476+
let { typeAnnotation } = node.returnType || node.typeAnnotation;
477+
478+
if (
479+
typeAnnotation.type === "TSTypePredicate" &&
480+
typeAnnotation.typeAnnotation
481+
) {
482+
typeAnnotation = typeAnnotation.typeAnnotation.typeAnnotation;
483+
}
484+
478485
if (
479-
returnTypeAnnotation.type === "TSInferType" &&
480-
returnTypeAnnotation.typeParameter.constraint
486+
typeAnnotation.type === "TSInferType" &&
487+
typeAnnotation.typeParameter.constraint
481488
) {
482489
return true;
483490
}
484491
}
492+
485493
if (name === "checkType" && parent.type === "TSConditionalType") {
486494
return true;
487495
}

Diff for: tests/format/typescript/conditional-types/__snapshots__/jsfmt.spec.js.snap

+54-14
Original file line numberDiff line numberDiff line change
@@ -278,20 +278,6 @@ type Unpacked<T> = T extends (infer U)[]
278278
================================================================================
279279
`;
280280
281-
exports[`issue-13275.ts format 1`] = `
282-
====================================options=====================================
283-
parsers: ["typescript"]
284-
printWidth: 80
285-
| printWidth
286-
=====================================input======================================
287-
type Foo<T> = T extends ((...a: any[]) => infer R extends string) ? R : never;
288-
289-
=====================================output=====================================
290-
type Foo<T> = T extends ((...a: any[]) => infer R extends string) ? R : never;
291-
292-
================================================================================
293-
`;
294-
295281
exports[`nested-in-condition.ts format 1`] = `
296282
====================================options=====================================
297283
parsers: ["typescript"]
@@ -431,3 +417,57 @@ type Unpacked<T> = T extends (infer U)[]
431417
432418
================================================================================
433419
`;
420+
421+
exports[`parentheses.ts format 1`] = `
422+
====================================options=====================================
423+
parsers: ["typescript"]
424+
printWidth: 80
425+
| printWidth
426+
=====================================input======================================
427+
// #13275
428+
type Foo<T> = T extends ((...a: any[]) => infer R extends string) ? R : never;
429+
type Foo<T> = T extends (new (...a: any[]) => infer R extends string) ? R : never;
430+
431+
// #14275
432+
type Test<T> = T extends ((
433+
token: TSESTree.Token
434+
) => token is infer U extends TSESTree.Token)
435+
? U
436+
: TSESTree.Token;
437+
type Test<T> = T extends ((
438+
token: TSESTree.Token
439+
) => asserts token is infer U extends TSESTree.Token)
440+
? U
441+
: TSESTree.Token;
442+
type Test<T> = T extends (new (
443+
token: TSESTree.Token
444+
) => token is infer U extends TSESTree.Token)
445+
? U
446+
: TSESTree.Token;
447+
448+
=====================================output=====================================
449+
// #13275
450+
type Foo<T> = T extends ((...a: any[]) => infer R extends string) ? R : never;
451+
type Foo<T> = T extends (new (...a: any[]) => infer R extends string)
452+
? R
453+
: never;
454+
455+
// #14275
456+
type Test<T> = T extends ((
457+
token: TSESTree.Token
458+
) => token is infer U extends TSESTree.Token)
459+
? U
460+
: TSESTree.Token;
461+
type Test<T> = T extends ((
462+
token: TSESTree.Token
463+
) => asserts token is infer U extends TSESTree.Token)
464+
? U
465+
: TSESTree.Token;
466+
type Test<T> = T extends (new (
467+
token: TSESTree.Token
468+
) => token is infer U extends TSESTree.Token)
469+
? U
470+
: TSESTree.Token;
471+
472+
================================================================================
473+
`;

Diff for: tests/format/typescript/conditional-types/issue-13275.ts

-1
This file was deleted.
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// #13275
2+
type Foo<T> = T extends ((...a: any[]) => infer R extends string) ? R : never;
3+
type Foo<T> = T extends (new (...a: any[]) => infer R extends string) ? R : never;
4+
5+
// #14275
6+
type Test<T> = T extends ((
7+
token: TSESTree.Token
8+
) => token is infer U extends TSESTree.Token)
9+
? U
10+
: TSESTree.Token;
11+
type Test<T> = T extends ((
12+
token: TSESTree.Token
13+
) => asserts token is infer U extends TSESTree.Token)
14+
? U
15+
: TSESTree.Token;
16+
type Test<T> = T extends (new (
17+
token: TSESTree.Token
18+
) => token is infer U extends TSESTree.Token)
19+
? U
20+
: TSESTree.Token;

0 commit comments

Comments
 (0)