From 1cec8dc7983791425e3710a2dab763d1d739ce5f Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 3 Jul 2016 16:45:27 -0700 Subject: [PATCH] All types can be null/undefined and thus falsy in regular type checking mode --- src/compiler/checker.ts | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 29f98529e29..8072659fa3f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -250,27 +250,27 @@ namespace ts { // The presence of a particular fact means that the given test is true for some (and possibly all) values // of that kind of type. BaseStringStrictFacts = TypeofEQString | TypeofNENumber | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NEUndefinedOrNull, - BaseStringFacts = BaseStringStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull, + BaseStringFacts = BaseStringStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy, StringStrictFacts = BaseStringStrictFacts | Truthy | Falsy, - StringFacts = BaseStringFacts | Truthy | Falsy, + StringFacts = BaseStringFacts | Truthy, EmptyStringStrictFacts = BaseStringStrictFacts | Falsy, - EmptyStringFacts = BaseStringFacts | Falsy, + EmptyStringFacts = BaseStringFacts, NonEmptyStringStrictFacts = BaseStringStrictFacts | Truthy, NonEmptyStringFacts = BaseStringFacts | Truthy, BaseNumberStrictFacts = TypeofEQNumber | TypeofNEString | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NEUndefinedOrNull, - BaseNumberFacts = BaseNumberStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull, + BaseNumberFacts = BaseNumberStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy, NumberStrictFacts = BaseNumberStrictFacts | Truthy | Falsy, - NumberFacts = BaseNumberFacts | Truthy | Falsy, + NumberFacts = BaseNumberFacts | Truthy, ZeroStrictFacts = BaseNumberStrictFacts | Falsy, - ZeroFacts = BaseNumberFacts | Falsy, + ZeroFacts = BaseNumberFacts, NonZeroStrictFacts = BaseNumberStrictFacts | Truthy, NonZeroFacts = BaseNumberFacts | Truthy, BaseBooleanStrictFacts = TypeofEQBoolean | TypeofNEString | TypeofNENumber | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NEUndefinedOrNull, - BaseBooleanFacts = BaseBooleanStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull, + BaseBooleanFacts = BaseBooleanStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy, BooleanStrictFacts = BaseBooleanStrictFacts | Truthy | Falsy, - BooleanFacts = BaseBooleanFacts | Truthy | Falsy, + BooleanFacts = BaseBooleanFacts | Truthy, FalseStrictFacts = BaseBooleanStrictFacts | Falsy, - FalseFacts = BaseBooleanFacts | Falsy, + FalseFacts = BaseBooleanFacts, TrueStrictFacts = BaseBooleanStrictFacts | Truthy, TrueFacts = BaseBooleanFacts | Truthy, SymbolStrictFacts = TypeofEQSymbol | TypeofNEString | TypeofNENumber | TypeofNEBoolean | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | NEUndefined | NENull | NEUndefinedOrNull | Truthy, @@ -7635,8 +7635,8 @@ namespace ts { const constraint = getConstraintOfTypeParameter(type); return constraint ? getTypeFacts(constraint) : TypeFacts.All; } - if (flags & TypeFlags.Intersection) { - return reduceLeft((type).types, (flags, type) => flags |= getTypeFacts(type), TypeFacts.None); + if (flags & TypeFlags.UnionOrIntersection) { + return reduceLeft((type).types, (flags, type) => flags |= getTypeFacts(type), TypeFacts.None); } return TypeFacts.All; } @@ -12722,11 +12722,13 @@ namespace ts { case SyntaxKind.InKeyword: return checkInExpression(left, right, leftType, rightType); case SyntaxKind.AmpersandAmpersandToken: - return !strictNullChecks ? rightType : - getTypeFacts(leftType) & TypeFacts.Truthy ? includeFalsyTypes(rightType, getFalsyFlags(leftType)) : leftType; + return getTypeFacts(leftType) & TypeFacts.Truthy ? + strictNullChecks ? includeFalsyTypes(rightType, getFalsyFlags(leftType)) : rightType : + leftType; case SyntaxKind.BarBarToken: - return !strictNullChecks ? getUnionType([leftType, rightType]) : - getTypeFacts(leftType) & TypeFacts.Truthy ? getUnionType([removeDefinitelyFalsyTypes(leftType), rightType]) : rightType; + return getTypeFacts(leftType) & TypeFacts.Falsy ? + getUnionType([removeDefinitelyFalsyTypes(leftType), rightType]) : + leftType; case SyntaxKind.EqualsToken: checkAssignmentOperator(rightType); return getRegularTypeOfObjectLiteral(rightType);