Skip to content

Commit a5029e3

Browse files
authored
Merge pull request #23794 from Microsoft/fixDiscriminatedContextualType
Fix discriminant checking in contextual types
2 parents 9d57903 + acee628 commit a5029e3

File tree

1 file changed

+22
-2
lines changed

1 file changed

+22
-2
lines changed

src/compiler/checker.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15307,6 +15307,26 @@ namespace ts {
1530715307
}
1530815308
}
1530915309

15310+
// Return true if the given expression is possibly a discriminant value. We limit the kinds of
15311+
// expressions we check to those that don't depend on their contextual type in order not to cause
15312+
// recursive (and possibly infinite) invocations of getContextualType.
15313+
function isPossiblyDiscriminantValue(node: Expression): boolean {
15314+
switch (node.kind) {
15315+
case SyntaxKind.StringLiteral:
15316+
case SyntaxKind.NumericLiteral:
15317+
case SyntaxKind.NoSubstitutionTemplateLiteral:
15318+
case SyntaxKind.TrueKeyword:
15319+
case SyntaxKind.FalseKeyword:
15320+
case SyntaxKind.NullKeyword:
15321+
case SyntaxKind.Identifier:
15322+
return true;
15323+
case SyntaxKind.PropertyAccessExpression:
15324+
case SyntaxKind.ParenthesizedExpression:
15325+
return isPossiblyDiscriminantValue((<PropertyAccessExpression | ParenthesizedExpression>node).expression);
15326+
}
15327+
return false;
15328+
}
15329+
1531015330
// Return the contextual type for a given expression node. During overload resolution, a contextual type may temporarily
1531115331
// be "pushed" onto a node using the contextualType property.
1531215332
function getApparentTypeOfContextualType(node: Expression): Type {
@@ -15320,8 +15340,8 @@ namespace ts {
1532015340
propLoop: for (const prop of node.properties) {
1532115341
if (!prop.symbol) continue;
1532215342
if (prop.kind !== SyntaxKind.PropertyAssignment) continue;
15323-
if (isDiscriminantProperty(contextualType, prop.symbol.escapedName)) {
15324-
const discriminatingType = getTypeOfNode(prop.initializer);
15343+
if (isPossiblyDiscriminantValue(prop.initializer) && isDiscriminantProperty(contextualType, prop.symbol.escapedName)) {
15344+
const discriminatingType = checkExpression(prop.initializer);
1532515345
for (const type of (contextualType as UnionType).types) {
1532615346
const targetType = getTypeOfPropertyOfType(type, prop.symbol.escapedName);
1532715347
if (targetType && checkTypeAssignableTo(discriminatingType, targetType, /*errorNode*/ undefined)) {

0 commit comments

Comments
 (0)