diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a297646d887c3..5525ff30ddab7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -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, (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((n).extendsType, containsReference)) { + return true; + } } + return !!forEachChild(node, containsReference); } return true; function containsReference(node: Node): boolean { diff --git a/tests/baselines/reference/conditionalTypes2.errors.txt b/tests/baselines/reference/conditionalTypes2.errors.txt index f17a55dd61c6f..4093bf46fb0ee 100644 --- a/tests/baselines/reference/conditionalTypes2.errors.txt +++ b/tests/baselines/reference/conditionalTypes2.errors.txt @@ -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 = U extends T ? { [K in keyof U]: number } : never; + type What = Hmm<{}, { a: string }> + const w: What = { a: 4 }; \ No newline at end of file diff --git a/tests/baselines/reference/conditionalTypes2.js b/tests/baselines/reference/conditionalTypes2.js index 4f4f35e821afb..cb35ac6cc2dfe 100644 --- a/tests/baselines/reference/conditionalTypes2.js +++ b/tests/baselines/reference/conditionalTypes2.js @@ -188,6 +188,12 @@ type ProductComplementComplement = { }; type PCCA = ProductComplementComplement['a']; type PCCB = ProductComplementComplement['b']; + +// Repro from #31326 + +type Hmm = 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 = U extends T ? { + [K in keyof U]: number; +} : never; +declare type What = Hmm<{}, { + a: string; +}>; +declare const w: What; diff --git a/tests/baselines/reference/conditionalTypes2.symbols b/tests/baselines/reference/conditionalTypes2.symbols index b164d26e45089..f665cbc3c71d9 100644 --- a/tests/baselines/reference/conditionalTypes2.symbols +++ b/tests/baselines/reference/conditionalTypes2.symbols @@ -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 = 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)) + diff --git a/tests/baselines/reference/conditionalTypes2.types b/tests/baselines/reference/conditionalTypes2.types index aac6ba47475c6..e3d949f268e90 100644 --- a/tests/baselines/reference/conditionalTypes2.types +++ b/tests/baselines/reference/conditionalTypes2.types @@ -431,3 +431,18 @@ type PCCA = ProductComplementComplement['a']; type PCCB = ProductComplementComplement['b']; >PCCB : Product<"b", 1> +// Repro from #31326 + +type Hmm = U extends T ? { [K in keyof U]: number } : never; +>Hmm : Hmm + +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 + diff --git a/tests/cases/conformance/types/conditional/conditionalTypes2.ts b/tests/cases/conformance/types/conditional/conditionalTypes2.ts index 4b65b5ddeb202..bb70093f23319 100644 --- a/tests/cases/conformance/types/conditional/conditionalTypes2.ts +++ b/tests/cases/conformance/types/conditional/conditionalTypes2.ts @@ -190,3 +190,9 @@ type ProductComplementComplement = { }; type PCCA = ProductComplementComplement['a']; type PCCB = ProductComplementComplement['b']; + +// Repro from #31326 + +type Hmm = U extends T ? { [K in keyof U]: number } : never; +type What = Hmm<{}, { a: string }> +const w: What = { a: 4 };