Skip to content

Commit bca2808

Browse files
authored
Merge pull request #31337 from microsoft/fixConditionalTypeParameterReference
Fix type parameter leakage in conditional types
2 parents d8f2702 + 1366cc7 commit bca2808

File tree

6 files changed

+69
-18
lines changed

6 files changed

+69
-18
lines changed

src/compiler/checker.ts

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10482,29 +10482,14 @@ namespace ts {
1048210482
return result;
1048310483
}
1048410484

10485-
function isPossiblyReferencedInConditionalType(tp: TypeParameter, node: Node) {
10486-
if (isTypeParameterPossiblyReferenced(tp, node)) {
10487-
return true;
10488-
}
10489-
while (node) {
10490-
if (node.kind === SyntaxKind.ConditionalType) {
10491-
if (isTypeParameterPossiblyReferenced(tp, (<ConditionalTypeNode>node).extendsType)) {
10492-
return true;
10493-
}
10494-
}
10495-
node = node.parent;
10496-
}
10497-
return false;
10498-
}
10499-
1050010485
function getTypeFromConditionalTypeNode(node: ConditionalTypeNode): Type {
1050110486
const links = getNodeLinks(node);
1050210487
if (!links.resolvedType) {
1050310488
const checkType = getTypeFromTypeNode(node.checkType);
1050410489
const aliasSymbol = getAliasSymbolForTypeNode(node);
1050510490
const aliasTypeArguments = getTypeArgumentsForAliasSymbol(aliasSymbol);
1050610491
const allOuterTypeParameters = getOuterTypeParameters(node, /*includeThisTypes*/ true);
10507-
const outerTypeParameters = aliasTypeArguments ? allOuterTypeParameters : filter(allOuterTypeParameters, tp => isPossiblyReferencedInConditionalType(tp, node));
10492+
const outerTypeParameters = aliasTypeArguments ? allOuterTypeParameters : filter(allOuterTypeParameters, tp => isTypeParameterPossiblyReferenced(tp, node));
1050810493
const root: ConditionalRoot = {
1050910494
node,
1051010495
checkType,
@@ -11198,9 +11183,12 @@ namespace ts {
1119811183
// type parameter, or if the node contains type queries, we consider the type parameter possibly referenced.
1119911184
if (tp.symbol && tp.symbol.declarations && tp.symbol.declarations.length === 1) {
1120011185
const container = tp.symbol.declarations[0].parent;
11201-
if (findAncestor(node, n => n.kind === SyntaxKind.Block ? "quit" : n === container)) {
11202-
return !!forEachChild(node, containsReference);
11186+
for (let n = node; n !== container; n = n.parent) {
11187+
if (!n || n.kind === SyntaxKind.Block || n.kind === SyntaxKind.ConditionalType && forEachChild((<ConditionalTypeNode>n).extendsType, containsReference)) {
11188+
return true;
11189+
}
1120311190
}
11191+
return !!forEachChild(node, containsReference);
1120411192
}
1120511193
return true;
1120611194
function containsReference(node: Node): boolean {

tests/baselines/reference/conditionalTypes2.errors.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,4 +267,10 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(75,12): error TS2
267267
};
268268
type PCCA = ProductComplementComplement['a'];
269269
type PCCB = ProductComplementComplement['b'];
270+
271+
// Repro from #31326
272+
273+
type Hmm<T, U extends T> = U extends T ? { [K in keyof U]: number } : never;
274+
type What = Hmm<{}, { a: string }>
275+
const w: What = { a: 4 };
270276

tests/baselines/reference/conditionalTypes2.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,12 @@ type ProductComplementComplement = {
188188
};
189189
type PCCA = ProductComplementComplement['a'];
190190
type PCCB = ProductComplementComplement['b'];
191+
192+
// Repro from #31326
193+
194+
type Hmm<T, U extends T> = U extends T ? { [K in keyof U]: number } : never;
195+
type What = Hmm<{}, { a: string }>
196+
const w: What = { a: 4 };
191197

192198

193199
//// [conditionalTypes2.js]
@@ -265,6 +271,7 @@ function foo(value) {
265271
toString2(value);
266272
}
267273
}
274+
var w = { a: 4 };
268275

269276

270277
//// [conditionalTypes2.d.ts]
@@ -392,3 +399,10 @@ declare type ProductComplementComplement = {
392399
};
393400
declare type PCCA = ProductComplementComplement['a'];
394401
declare type PCCB = ProductComplementComplement['b'];
402+
declare type Hmm<T, U extends T> = U extends T ? {
403+
[K in keyof U]: number;
404+
} : never;
405+
declare type What = Hmm<{}, {
406+
a: string;
407+
}>;
408+
declare const w: What;

tests/baselines/reference/conditionalTypes2.symbols

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,3 +685,25 @@ type PCCB = ProductComplementComplement['b'];
685685
>PCCB : Symbol(PCCB, Decl(conditionalTypes2.ts, 187, 45))
686686
>ProductComplementComplement : Symbol(ProductComplementComplement, Decl(conditionalTypes2.ts, 181, 34))
687687

688+
// Repro from #31326
689+
690+
type Hmm<T, U extends T> = U extends T ? { [K in keyof U]: number } : never;
691+
>Hmm : Symbol(Hmm, Decl(conditionalTypes2.ts, 188, 45))
692+
>T : Symbol(T, Decl(conditionalTypes2.ts, 192, 9))
693+
>U : Symbol(U, Decl(conditionalTypes2.ts, 192, 11))
694+
>T : Symbol(T, Decl(conditionalTypes2.ts, 192, 9))
695+
>U : Symbol(U, Decl(conditionalTypes2.ts, 192, 11))
696+
>T : Symbol(T, Decl(conditionalTypes2.ts, 192, 9))
697+
>K : Symbol(K, Decl(conditionalTypes2.ts, 192, 44))
698+
>U : Symbol(U, Decl(conditionalTypes2.ts, 192, 11))
699+
700+
type What = Hmm<{}, { a: string }>
701+
>What : Symbol(What, Decl(conditionalTypes2.ts, 192, 76))
702+
>Hmm : Symbol(Hmm, Decl(conditionalTypes2.ts, 188, 45))
703+
>a : Symbol(a, Decl(conditionalTypes2.ts, 193, 21))
704+
705+
const w: What = { a: 4 };
706+
>w : Symbol(w, Decl(conditionalTypes2.ts, 194, 5))
707+
>What : Symbol(What, Decl(conditionalTypes2.ts, 192, 76))
708+
>a : Symbol(a, Decl(conditionalTypes2.ts, 194, 17))
709+

tests/baselines/reference/conditionalTypes2.types

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,3 +431,18 @@ type PCCA = ProductComplementComplement['a'];
431431
type PCCB = ProductComplementComplement['b'];
432432
>PCCB : Product<"b", 1>
433433

434+
// Repro from #31326
435+
436+
type Hmm<T, U extends T> = U extends T ? { [K in keyof U]: number } : never;
437+
>Hmm : Hmm<T, U>
438+
439+
type What = Hmm<{}, { a: string }>
440+
>What : { a: number; }
441+
>a : string
442+
443+
const w: What = { a: 4 };
444+
>w : { a: number; }
445+
>{ a: 4 } : { a: number; }
446+
>a : number
447+
>4 : 4
448+

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,3 +190,9 @@ type ProductComplementComplement = {
190190
};
191191
type PCCA = ProductComplementComplement['a'];
192192
type PCCB = ProductComplementComplement['b'];
193+
194+
// Repro from #31326
195+
196+
type Hmm<T, U extends T> = U extends T ? { [K in keyof U]: number } : never;
197+
type What = Hmm<{}, { a: string }>
198+
const w: What = { a: 4 };

0 commit comments

Comments
 (0)