From fc85bc5a8aeafd69215bfdb308fbd064909b11c9 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 31 Jul 2016 07:57:01 -0700 Subject: [PATCH] Use "best choice type" for || and ?: operators --- src/compiler/checker.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 33abcb2af12..7d878765494 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12896,6 +12896,14 @@ namespace ts { return (target.flags & TypeFlags.Nullable) !== 0 || isTypeComparableTo(source, target); } + function getBestChoiceType(type1: Type, type2: Type): Type { + const firstAssignableToSecond = isTypeAssignableTo(type1, type2); + const secondAssignableToFirst = isTypeAssignableTo(type2, type1); + return secondAssignableToFirst && !firstAssignableToSecond ? type1 : + firstAssignableToSecond && !secondAssignableToFirst ? type2 : + getUnionType([type1, type2], /*subtypeReduction*/ true); + } + function checkBinaryExpression(node: BinaryExpression, contextualMapper?: TypeMapper) { return checkBinaryLikeExpression(node.left, node.operatorToken, node.right, contextualMapper, node); } @@ -13039,7 +13047,7 @@ namespace ts { leftType; case SyntaxKind.BarBarToken: return getTypeFacts(leftType) & TypeFacts.Falsy ? - getUnionType([removeDefinitelyFalsyTypes(leftType), rightType], /*subtypeReduction*/ true) : + getBestChoiceType(removeDefinitelyFalsyTypes(leftType), rightType) : leftType; case SyntaxKind.EqualsToken: checkAssignmentOperator(rightType); @@ -13166,7 +13174,7 @@ namespace ts { checkExpression(node.condition); const type1 = checkExpression(node.whenTrue, contextualMapper); const type2 = checkExpression(node.whenFalse, contextualMapper); - return getUnionType([type1, type2], /*subtypeReduction*/ true); + return getBestChoiceType(type1, type2); } function typeContainsLiteralFromEnum(type: Type, enumType: EnumType) {