Skip to content

Commit 2730cb2

Browse files
authored
Only skip any checks for unwrapped tuples in conditionals, rather than all nondistributive conditionals for backcompat (#42447)
1 parent 9dbfaee commit 2730cb2

8 files changed

+107
-4
lines changed

src/compiler/checker.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14647,6 +14647,7 @@ namespace ts {
1464714647
// types of the form 'A extends B ? X : C extends D ? Y : E extends F ? Z : ...' as a single construct for
1464814648
// purposes of resolution. This means such types aren't subject to the instatiation depth limiter.
1464914649
while (true) {
14650+
const isUnwrapped = isTypicalNondistributiveConditional(root);
1465014651
const checkType = instantiateType(unwrapNondistributiveConditionalTuple(root, root.checkType), mapper);
1465114652
const checkTypeInstantiable = isGenericObjectType(checkType) || isGenericIndexType(checkType);
1465214653
const extendsType = instantiateType(unwrapNondistributiveConditionalTuple(root, root.extendsType), mapper);
@@ -14672,9 +14673,9 @@ namespace ts {
1467214673
// types with type parameters mapped to the wildcard type, the most permissive instantiations
1467314674
// possible (the wildcard type is assignable to and from all types). If those are not related,
1467414675
// then no instantiations will be and we can just return the false branch type.
14675-
if (!(inferredExtendsType.flags & TypeFlags.AnyOrUnknown) && ((checkType.flags & TypeFlags.Any && root.isDistributive) || !isTypeAssignableTo(getPermissiveInstantiation(checkType), getPermissiveInstantiation(inferredExtendsType)))) {
14676+
if (!(inferredExtendsType.flags & TypeFlags.AnyOrUnknown) && ((checkType.flags & TypeFlags.Any && !isUnwrapped) || !isTypeAssignableTo(getPermissiveInstantiation(checkType), getPermissiveInstantiation(inferredExtendsType)))) {
1467614677
// Return union of trueType and falseType for 'any' since it matches anything
14677-
if (checkType.flags & TypeFlags.Any && root.isDistributive) {
14678+
if (checkType.flags & TypeFlags.Any && !isUnwrapped) {
1467814679
(extraTypes || (extraTypes = [])).push(instantiateType(getTypeFromTypeNode(root.node.trueType), combinedMapper || mapper));
1467914680
}
1468014681
// If falseType is an immediately nested conditional type that isn't distributive or has an
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
tests/cases/compiler/conditionalAnyCheckTypePicksBothBranches.ts(9,1): error TS2322: Type '0' is not assignable to type '1'.
2+
3+
4+
==== tests/cases/compiler/conditionalAnyCheckTypePicksBothBranches.ts (1 errors) ====
5+
type T = any extends number ? 1 : 0;
6+
let x: T;
7+
x = 1;
8+
x = 0; // not an error
9+
10+
type U = [any] extends [number] ? 1 : 0;
11+
let y: U;
12+
y = 1;
13+
y = 0; // error
14+
~
15+
!!! error TS2322: Type '0' is not assignable to type '1'.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//// [conditionalAnyCheckTypePicksBothBranches.ts]
2+
type T = any extends number ? 1 : 0;
3+
let x: T;
4+
x = 1;
5+
x = 0; // not an error
6+
7+
type U = [any] extends [number] ? 1 : 0;
8+
let y: U;
9+
y = 1;
10+
y = 0; // error
11+
12+
//// [conditionalAnyCheckTypePicksBothBranches.js]
13+
var x;
14+
x = 1;
15+
x = 0; // not an error
16+
var y;
17+
y = 1;
18+
y = 0; // error
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
=== tests/cases/compiler/conditionalAnyCheckTypePicksBothBranches.ts ===
2+
type T = any extends number ? 1 : 0;
3+
>T : Symbol(T, Decl(conditionalAnyCheckTypePicksBothBranches.ts, 0, 0))
4+
5+
let x: T;
6+
>x : Symbol(x, Decl(conditionalAnyCheckTypePicksBothBranches.ts, 1, 3))
7+
>T : Symbol(T, Decl(conditionalAnyCheckTypePicksBothBranches.ts, 0, 0))
8+
9+
x = 1;
10+
>x : Symbol(x, Decl(conditionalAnyCheckTypePicksBothBranches.ts, 1, 3))
11+
12+
x = 0; // not an error
13+
>x : Symbol(x, Decl(conditionalAnyCheckTypePicksBothBranches.ts, 1, 3))
14+
15+
type U = [any] extends [number] ? 1 : 0;
16+
>U : Symbol(U, Decl(conditionalAnyCheckTypePicksBothBranches.ts, 3, 6))
17+
18+
let y: U;
19+
>y : Symbol(y, Decl(conditionalAnyCheckTypePicksBothBranches.ts, 6, 3))
20+
>U : Symbol(U, Decl(conditionalAnyCheckTypePicksBothBranches.ts, 3, 6))
21+
22+
y = 1;
23+
>y : Symbol(y, Decl(conditionalAnyCheckTypePicksBothBranches.ts, 6, 3))
24+
25+
y = 0; // error
26+
>y : Symbol(y, Decl(conditionalAnyCheckTypePicksBothBranches.ts, 6, 3))
27+
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
=== tests/cases/compiler/conditionalAnyCheckTypePicksBothBranches.ts ===
2+
type T = any extends number ? 1 : 0;
3+
>T : 0 | 1
4+
5+
let x: T;
6+
>x : 0 | 1
7+
8+
x = 1;
9+
>x = 1 : 1
10+
>x : 0 | 1
11+
>1 : 1
12+
13+
x = 0; // not an error
14+
>x = 0 : 0
15+
>x : 0 | 1
16+
>0 : 0
17+
18+
type U = [any] extends [number] ? 1 : 0;
19+
>U : 1
20+
21+
let y: U;
22+
>y : 1
23+
24+
y = 1;
25+
>y = 1 : 1
26+
>y : 1
27+
>1 : 1
28+
29+
y = 0; // error
30+
>y = 0 : 0
31+
>y : 1
32+
>0 : 0
33+

tests/baselines/reference/inferTypes1.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ type T61<T> = infer A extends infer B ? infer C : infer D; // Error
257257
>T61 : T61<T>
258258

259259
type T62<T> = U extends (infer U)[] ? U : U; // Error
260-
>T62 : unknown
260+
>T62 : any
261261

262262
type T63<T> = T extends (infer A extends infer B ? infer C : infer D) ? string : number;
263263
>T63 : T63<T>

tests/baselines/reference/recursiveConditionalTypes.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ type TT3 = TupleOf<number, any>;
105105
>TT3 : number[]
106106

107107
type TT4 = TupleOf<number, 100>; // Depth error
108-
>TT4 : [any, ...any[]]
108+
>TT4 : any
109109

110110
function f22<N extends number, M extends N>(tn: TupleOf<number, N>, tm: TupleOf<number, M>) {
111111
>f22 : <N extends number, M extends N>(tn: TupleOf<number, N>, tm: TupleOf<number, M>) => void
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
type T = any extends number ? 1 : 0;
2+
let x: T;
3+
x = 1;
4+
x = 0; // not an error
5+
6+
type U = [any] extends [number] ? 1 : 0;
7+
let y: U;
8+
y = 1;
9+
y = 0; // error

0 commit comments

Comments
 (0)