Merge pull request #31337 from microsoft/fixConditionalTypeParameterReference

Fix type parameter leakage in conditional types
This commit is contained in:
Anders Hejlsberg
2019-05-10 13:11:45 -07:00
committed by GitHub
6 changed files with 69 additions and 18 deletions

View File

@@ -10482,21 +10482,6 @@ namespace ts {
return result;
}
function isPossiblyReferencedInConditionalType(tp: TypeParameter, node: Node) {
if (isTypeParameterPossiblyReferenced(tp, node)) {
return true;
}
while (node) {
if (node.kind === SyntaxKind.ConditionalType) {
if (isTypeParameterPossiblyReferenced(tp, (<ConditionalTypeNode>node).extendsType)) {
return true;
}
}
node = node.parent;
}
return false;
}
function getTypeFromConditionalTypeNode(node: ConditionalTypeNode): Type {
const links = getNodeLinks(node);
if (!links.resolvedType) {
@@ -10504,7 +10489,7 @@ namespace ts {
const aliasSymbol = getAliasSymbolForTypeNode(node);
const aliasTypeArguments = getTypeArgumentsForAliasSymbol(aliasSymbol);
const allOuterTypeParameters = getOuterTypeParameters(node, /*includeThisTypes*/ true);
const outerTypeParameters = aliasTypeArguments ? allOuterTypeParameters : filter(allOuterTypeParameters, tp => isPossiblyReferencedInConditionalType(tp, node));
const outerTypeParameters = aliasTypeArguments ? allOuterTypeParameters : filter(allOuterTypeParameters, tp => isTypeParameterPossiblyReferenced(tp, node));
const root: ConditionalRoot = {
node,
checkType,
@@ -11198,9 +11183,12 @@ namespace ts {
// type parameter, or if the node contains type queries, we consider the type parameter possibly referenced.
if (tp.symbol && tp.symbol.declarations && tp.symbol.declarations.length === 1) {
const container = tp.symbol.declarations[0].parent;
if (findAncestor(node, n => n.kind === SyntaxKind.Block ? "quit" : n === container)) {
return !!forEachChild(node, containsReference);
for (let n = node; n !== container; n = n.parent) {
if (!n || n.kind === SyntaxKind.Block || n.kind === SyntaxKind.ConditionalType && forEachChild((<ConditionalTypeNode>n).extendsType, containsReference)) {
return true;
}
}
return !!forEachChild(node, containsReference);
}
return true;
function containsReference(node: Node): boolean {

View File

@@ -267,4 +267,10 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(75,12): error TS2
};
type PCCA = ProductComplementComplement['a'];
type PCCB = ProductComplementComplement['b'];
// Repro from #31326
type Hmm<T, U extends T> = U extends T ? { [K in keyof U]: number } : never;
type What = Hmm<{}, { a: string }>
const w: What = { a: 4 };

View File

@@ -188,6 +188,12 @@ type ProductComplementComplement = {
};
type PCCA = ProductComplementComplement['a'];
type PCCB = ProductComplementComplement['b'];
// Repro from #31326
type Hmm<T, U extends T> = U extends T ? { [K in keyof U]: number } : never;
type What = Hmm<{}, { a: string }>
const w: What = { a: 4 };
//// [conditionalTypes2.js]
@@ -265,6 +271,7 @@ function foo(value) {
toString2(value);
}
}
var w = { a: 4 };
//// [conditionalTypes2.d.ts]
@@ -392,3 +399,10 @@ declare type ProductComplementComplement = {
};
declare type PCCA = ProductComplementComplement['a'];
declare type PCCB = ProductComplementComplement['b'];
declare type Hmm<T, U extends T> = U extends T ? {
[K in keyof U]: number;
} : never;
declare type What = Hmm<{}, {
a: string;
}>;
declare const w: What;

View File

@@ -685,3 +685,25 @@ type PCCB = ProductComplementComplement['b'];
>PCCB : Symbol(PCCB, Decl(conditionalTypes2.ts, 187, 45))
>ProductComplementComplement : Symbol(ProductComplementComplement, Decl(conditionalTypes2.ts, 181, 34))
// Repro from #31326
type Hmm<T, U extends T> = U extends T ? { [K in keyof U]: number } : never;
>Hmm : Symbol(Hmm, Decl(conditionalTypes2.ts, 188, 45))
>T : Symbol(T, Decl(conditionalTypes2.ts, 192, 9))
>U : Symbol(U, Decl(conditionalTypes2.ts, 192, 11))
>T : Symbol(T, Decl(conditionalTypes2.ts, 192, 9))
>U : Symbol(U, Decl(conditionalTypes2.ts, 192, 11))
>T : Symbol(T, Decl(conditionalTypes2.ts, 192, 9))
>K : Symbol(K, Decl(conditionalTypes2.ts, 192, 44))
>U : Symbol(U, Decl(conditionalTypes2.ts, 192, 11))
type What = Hmm<{}, { a: string }>
>What : Symbol(What, Decl(conditionalTypes2.ts, 192, 76))
>Hmm : Symbol(Hmm, Decl(conditionalTypes2.ts, 188, 45))
>a : Symbol(a, Decl(conditionalTypes2.ts, 193, 21))
const w: What = { a: 4 };
>w : Symbol(w, Decl(conditionalTypes2.ts, 194, 5))
>What : Symbol(What, Decl(conditionalTypes2.ts, 192, 76))
>a : Symbol(a, Decl(conditionalTypes2.ts, 194, 17))

View File

@@ -431,3 +431,18 @@ type PCCA = ProductComplementComplement['a'];
type PCCB = ProductComplementComplement['b'];
>PCCB : Product<"b", 1>
// Repro from #31326
type Hmm<T, U extends T> = U extends T ? { [K in keyof U]: number } : never;
>Hmm : Hmm<T, U>
type What = Hmm<{}, { a: string }>
>What : { a: number; }
>a : string
const w: What = { a: 4 };
>w : { a: number; }
>{ a: 4 } : { a: number; }
>a : number
>4 : 4

View File

@@ -190,3 +190,9 @@ type ProductComplementComplement = {
};
type PCCA = ProductComplementComplement['a'];
type PCCB = ProductComplementComplement['b'];
// Repro from #31326
type Hmm<T, U extends T> = U extends T ? { [K in keyof U]: number } : never;
type What = Hmm<{}, { a: string }>
const w: What = { a: 4 };