Skip to content

Commit 751eab9

Browse files
authored
Merge pull request #23067 from Microsoft/fixTPReferenceInConditional
Fix type parameter reference checks in conditional types
2 parents e6fa4e4 + c2f96a3 commit 751eab9

File tree

6 files changed

+233
-6
lines changed

6 files changed

+233
-6
lines changed

src/compiler/checker.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8466,15 +8466,19 @@ namespace ts {
84668466
return result;
84678467
}
84688468

8469-
function getTopConditionalType(node: Node): ConditionalTypeNode {
8470-
let result: ConditionalTypeNode;
8469+
function isPossiblyReferencedInConditionalType(tp: TypeParameter, node: Node) {
8470+
if (isTypeParameterPossiblyReferenced(tp, node)) {
8471+
return true;
8472+
}
84718473
while (node) {
84728474
if (node.kind === SyntaxKind.ConditionalType) {
8473-
result = <ConditionalTypeNode>node;
8475+
if (isTypeParameterPossiblyReferenced(tp, (<ConditionalTypeNode>node).extendsType)) {
8476+
return true;
8477+
}
84748478
}
84758479
node = node.parent;
84768480
}
8477-
return result;
8481+
return false;
84788482
}
84798483

84808484
function getTypeFromConditionalTypeNode(node: ConditionalTypeNode): Type {
@@ -8483,8 +8487,7 @@ namespace ts {
84838487
const checkType = getTypeFromTypeNode(node.checkType);
84848488
const aliasTypeArguments = getAliasTypeArgumentsForTypeNode(node);
84858489
const allOuterTypeParameters = getOuterTypeParameters(node, /*includeThisTypes*/ true);
8486-
const topNode = getTopConditionalType(node);
8487-
const outerTypeParameters = aliasTypeArguments ? allOuterTypeParameters : filter(allOuterTypeParameters, tp => isTypeParameterPossiblyReferenced(tp, topNode));
8490+
const outerTypeParameters = aliasTypeArguments ? allOuterTypeParameters : filter(allOuterTypeParameters, tp => isPossiblyReferencedInConditionalType(tp, node));
84888491
const root: ConditionalRoot = {
84898492
node,
84908493
checkType,

tests/baselines/reference/conditionalTypes2.errors.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,4 +176,19 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(75,12): error TS2
176176
toString2(value);
177177
}
178178
}
179+
180+
// Repro from #23052
181+
182+
type A<T, V, E> =
183+
T extends object
184+
? { [Q in { [P in keyof T]: T[P] extends V ? P : P; }[keyof T]]: A<T[Q], V, E>; }
185+
: T extends V ? T : never;
186+
187+
type B<T, V> =
188+
T extends object
189+
? { [Q in { [P in keyof T]: T[P] extends V ? P : P; }[keyof T]]: B<T[Q], V>; }
190+
: T extends V ? T : never;
191+
192+
type C<T, V, E> =
193+
{ [Q in { [P in keyof T]: T[P] extends V ? P : P; }[keyof T]]: C<T[Q], V, E>; };
179194

tests/baselines/reference/conditionalTypes2.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,21 @@ function foo<T>(value: T) {
119119
toString2(value);
120120
}
121121
}
122+
123+
// Repro from #23052
124+
125+
type A<T, V, E> =
126+
T extends object
127+
? { [Q in { [P in keyof T]: T[P] extends V ? P : P; }[keyof T]]: A<T[Q], V, E>; }
128+
: T extends V ? T : never;
129+
130+
type B<T, V> =
131+
T extends object
132+
? { [Q in { [P in keyof T]: T[P] extends V ? P : P; }[keyof T]]: B<T[Q], V>; }
133+
: T extends V ? T : never;
134+
135+
type C<T, V, E> =
136+
{ [Q in { [P in keyof T]: T[P] extends V ? P : P; }[keyof T]]: C<T[Q], V, E>; };
122137

123138

124139
//// [conditionalTypes2.js]
@@ -254,3 +269,18 @@ interface B1<T> extends A1<T> {
254269
declare function toString1(value: object | Function): string;
255270
declare function toString2(value: Function): string;
256271
declare function foo<T>(value: T): void;
272+
declare type A<T, V, E> = T extends object ? {
273+
[Q in {
274+
[P in keyof T]: T[P] extends V ? P : P;
275+
}[keyof T]]: A<T[Q], V, E>;
276+
} : T extends V ? T : never;
277+
declare type B<T, V> = T extends object ? {
278+
[Q in {
279+
[P in keyof T]: T[P] extends V ? P : P;
280+
}[keyof T]]: B<T[Q], V>;
281+
} : T extends V ? T : never;
282+
declare type C<T, V, E> = {
283+
[Q in {
284+
[P in keyof T]: T[P] extends V ? P : P;
285+
}[keyof T]]: C<T[Q], V, E>;
286+
};

tests/baselines/reference/conditionalTypes2.symbols

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,3 +414,85 @@ function foo<T>(value: T) {
414414
}
415415
}
416416

417+
// Repro from #23052
418+
419+
type A<T, V, E> =
420+
>A : Symbol(A, Decl(conditionalTypes2.ts, 119, 1))
421+
>T : Symbol(T, Decl(conditionalTypes2.ts, 123, 7))
422+
>V : Symbol(V, Decl(conditionalTypes2.ts, 123, 9))
423+
>E : Symbol(E, Decl(conditionalTypes2.ts, 123, 12))
424+
425+
T extends object
426+
>T : Symbol(T, Decl(conditionalTypes2.ts, 123, 7))
427+
428+
? { [Q in { [P in keyof T]: T[P] extends V ? P : P; }[keyof T]]: A<T[Q], V, E>; }
429+
>Q : Symbol(Q, Decl(conditionalTypes2.ts, 125, 9))
430+
>P : Symbol(P, Decl(conditionalTypes2.ts, 125, 17))
431+
>T : Symbol(T, Decl(conditionalTypes2.ts, 123, 7))
432+
>T : Symbol(T, Decl(conditionalTypes2.ts, 123, 7))
433+
>P : Symbol(P, Decl(conditionalTypes2.ts, 125, 17))
434+
>V : Symbol(V, Decl(conditionalTypes2.ts, 123, 9))
435+
>P : Symbol(P, Decl(conditionalTypes2.ts, 125, 17))
436+
>P : Symbol(P, Decl(conditionalTypes2.ts, 125, 17))
437+
>T : Symbol(T, Decl(conditionalTypes2.ts, 123, 7))
438+
>A : Symbol(A, Decl(conditionalTypes2.ts, 119, 1))
439+
>T : Symbol(T, Decl(conditionalTypes2.ts, 123, 7))
440+
>Q : Symbol(Q, Decl(conditionalTypes2.ts, 125, 9))
441+
>V : Symbol(V, Decl(conditionalTypes2.ts, 123, 9))
442+
>E : Symbol(E, Decl(conditionalTypes2.ts, 123, 12))
443+
444+
: T extends V ? T : never;
445+
>T : Symbol(T, Decl(conditionalTypes2.ts, 123, 7))
446+
>V : Symbol(V, Decl(conditionalTypes2.ts, 123, 9))
447+
>T : Symbol(T, Decl(conditionalTypes2.ts, 123, 7))
448+
449+
type B<T, V> =
450+
>B : Symbol(B, Decl(conditionalTypes2.ts, 126, 30))
451+
>T : Symbol(T, Decl(conditionalTypes2.ts, 128, 7))
452+
>V : Symbol(V, Decl(conditionalTypes2.ts, 128, 9))
453+
454+
T extends object
455+
>T : Symbol(T, Decl(conditionalTypes2.ts, 128, 7))
456+
457+
? { [Q in { [P in keyof T]: T[P] extends V ? P : P; }[keyof T]]: B<T[Q], V>; }
458+
>Q : Symbol(Q, Decl(conditionalTypes2.ts, 130, 9))
459+
>P : Symbol(P, Decl(conditionalTypes2.ts, 130, 17))
460+
>T : Symbol(T, Decl(conditionalTypes2.ts, 128, 7))
461+
>T : Symbol(T, Decl(conditionalTypes2.ts, 128, 7))
462+
>P : Symbol(P, Decl(conditionalTypes2.ts, 130, 17))
463+
>V : Symbol(V, Decl(conditionalTypes2.ts, 128, 9))
464+
>P : Symbol(P, Decl(conditionalTypes2.ts, 130, 17))
465+
>P : Symbol(P, Decl(conditionalTypes2.ts, 130, 17))
466+
>T : Symbol(T, Decl(conditionalTypes2.ts, 128, 7))
467+
>B : Symbol(B, Decl(conditionalTypes2.ts, 126, 30))
468+
>T : Symbol(T, Decl(conditionalTypes2.ts, 128, 7))
469+
>Q : Symbol(Q, Decl(conditionalTypes2.ts, 130, 9))
470+
>V : Symbol(V, Decl(conditionalTypes2.ts, 128, 9))
471+
472+
: T extends V ? T : never;
473+
>T : Symbol(T, Decl(conditionalTypes2.ts, 128, 7))
474+
>V : Symbol(V, Decl(conditionalTypes2.ts, 128, 9))
475+
>T : Symbol(T, Decl(conditionalTypes2.ts, 128, 7))
476+
477+
type C<T, V, E> =
478+
>C : Symbol(C, Decl(conditionalTypes2.ts, 131, 30))
479+
>T : Symbol(T, Decl(conditionalTypes2.ts, 133, 7))
480+
>V : Symbol(V, Decl(conditionalTypes2.ts, 133, 9))
481+
>E : Symbol(E, Decl(conditionalTypes2.ts, 133, 12))
482+
483+
{ [Q in { [P in keyof T]: T[P] extends V ? P : P; }[keyof T]]: C<T[Q], V, E>; };
484+
>Q : Symbol(Q, Decl(conditionalTypes2.ts, 134, 5))
485+
>P : Symbol(P, Decl(conditionalTypes2.ts, 134, 13))
486+
>T : Symbol(T, Decl(conditionalTypes2.ts, 133, 7))
487+
>T : Symbol(T, Decl(conditionalTypes2.ts, 133, 7))
488+
>P : Symbol(P, Decl(conditionalTypes2.ts, 134, 13))
489+
>V : Symbol(V, Decl(conditionalTypes2.ts, 133, 9))
490+
>P : Symbol(P, Decl(conditionalTypes2.ts, 134, 13))
491+
>P : Symbol(P, Decl(conditionalTypes2.ts, 134, 13))
492+
>T : Symbol(T, Decl(conditionalTypes2.ts, 133, 7))
493+
>C : Symbol(C, Decl(conditionalTypes2.ts, 131, 30))
494+
>T : Symbol(T, Decl(conditionalTypes2.ts, 133, 7))
495+
>Q : Symbol(Q, Decl(conditionalTypes2.ts, 134, 5))
496+
>V : Symbol(V, Decl(conditionalTypes2.ts, 133, 9))
497+
>E : Symbol(E, Decl(conditionalTypes2.ts, 133, 12))
498+

tests/baselines/reference/conditionalTypes2.types

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,3 +444,85 @@ function foo<T>(value: T) {
444444
}
445445
}
446446

447+
// Repro from #23052
448+
449+
type A<T, V, E> =
450+
>A : A<T, V, E>
451+
>T : T
452+
>V : V
453+
>E : E
454+
455+
T extends object
456+
>T : T
457+
458+
? { [Q in { [P in keyof T]: T[P] extends V ? P : P; }[keyof T]]: A<T[Q], V, E>; }
459+
>Q : Q
460+
>P : P
461+
>T : T
462+
>T : T
463+
>P : P
464+
>V : V
465+
>P : P
466+
>P : P
467+
>T : T
468+
>A : A<T, V, E>
469+
>T : T
470+
>Q : Q
471+
>V : V
472+
>E : E
473+
474+
: T extends V ? T : never;
475+
>T : T
476+
>V : V
477+
>T : T
478+
479+
type B<T, V> =
480+
>B : B<T, V>
481+
>T : T
482+
>V : V
483+
484+
T extends object
485+
>T : T
486+
487+
? { [Q in { [P in keyof T]: T[P] extends V ? P : P; }[keyof T]]: B<T[Q], V>; }
488+
>Q : Q
489+
>P : P
490+
>T : T
491+
>T : T
492+
>P : P
493+
>V : V
494+
>P : P
495+
>P : P
496+
>T : T
497+
>B : B<T, V>
498+
>T : T
499+
>Q : Q
500+
>V : V
501+
502+
: T extends V ? T : never;
503+
>T : T
504+
>V : V
505+
>T : T
506+
507+
type C<T, V, E> =
508+
>C : C<T, V, E>
509+
>T : T
510+
>V : V
511+
>E : E
512+
513+
{ [Q in { [P in keyof T]: T[P] extends V ? P : P; }[keyof T]]: C<T[Q], V, E>; };
514+
>Q : Q
515+
>P : P
516+
>T : T
517+
>T : T
518+
>P : P
519+
>V : V
520+
>P : P
521+
>P : P
522+
>T : T
523+
>C : C<T, V, E>
524+
>T : T
525+
>Q : Q
526+
>V : V
527+
>E : E
528+

tests/cases/conformance/types/conditional/conditionalTypes2.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,18 @@ function foo<T>(value: T) {
121121
toString2(value);
122122
}
123123
}
124+
125+
// Repro from #23052
126+
127+
type A<T, V, E> =
128+
T extends object
129+
? { [Q in { [P in keyof T]: T[P] extends V ? P : P; }[keyof T]]: A<T[Q], V, E>; }
130+
: T extends V ? T : never;
131+
132+
type B<T, V> =
133+
T extends object
134+
? { [Q in { [P in keyof T]: T[P] extends V ? P : P; }[keyof T]]: B<T[Q], V>; }
135+
: T extends V ? T : never;
136+
137+
type C<T, V, E> =
138+
{ [Q in { [P in keyof T]: T[P] extends V ? P : P; }[keyof T]]: C<T[Q], V, E>; };

0 commit comments

Comments
 (0)