diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e0ab7922564..342c3f22e30 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1226,8 +1226,11 @@ export const enum TypeFacts { Falsy = 1 << 23, // !x IsUndefined = 1 << 24, // Contains undefined or intersection with undefined IsNull = 1 << 25, // Contains null or intersection with null + IsPossiblyUndefined = 1 << 26, // Possibly undefined + IsPossiblyNull = 1 << 27, // Possibly null IsUndefinedOrNull = IsUndefined | IsNull, - All = (1 << 27) - 1, + IsPossiblyUndefinedOrNull = IsPossiblyUndefined | IsPossiblyNull, + All = (1 << 29) - 1, // The following members encode facts about particular kinds of types for use in the getTypeFacts function. // The presence of a particular fact means that the given test is true for some (and possibly all) values // of that kind of type. @@ -1270,11 +1273,12 @@ export const enum TypeFacts { FunctionStrictFacts = TypeofEQFunction | TypeofEQHostObject | TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | NEUndefined | NENull | NEUndefinedOrNull | Truthy, FunctionFacts = FunctionStrictFacts | EQUndefined | EQNull | EQUndefinedOrNull | Falsy, VoidFacts = TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | EQUndefined | EQUndefinedOrNull | NENull | Falsy, - UndefinedFacts = TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | EQUndefined | EQUndefinedOrNull | NENull | Falsy | IsUndefined, - NullFacts = TypeofEQObject | TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEFunction | TypeofNEHostObject | EQNull | EQUndefinedOrNull | NEUndefined | Falsy | IsNull, - EmptyObjectStrictFacts = All & ~(EQUndefined | EQNull | EQUndefinedOrNull | IsUndefinedOrNull), - EmptyObjectFacts = All & ~IsUndefinedOrNull, - UnknownFacts = All & ~IsUndefinedOrNull, + UndefinedFacts = TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | TypeofNEHostObject | EQUndefined | EQUndefinedOrNull | NENull | Falsy | IsUndefined | IsPossiblyUndefined, + NullFacts = TypeofEQObject | TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEFunction | TypeofNEHostObject | EQNull | EQUndefinedOrNull | NEUndefined | Falsy | IsNull | IsPossiblyNull, + EmptyObjectStrictFacts = All & ~(EQUndefined | EQNull | EQUndefinedOrNull | IsUndefinedOrNull | IsPossiblyUndefinedOrNull), + EmptyObjectFacts = All & ~(IsUndefinedOrNull | IsPossiblyUndefinedOrNull), + UnknownStrictFacts = All & ~IsUndefinedOrNull, + UnknownFacts = All & ~(IsUndefinedOrNull | IsPossiblyUndefinedOrNull), AllTypeofNE = TypeofNEString | TypeofNENumber | TypeofNEBigInt | TypeofNEBoolean | TypeofNESymbol | TypeofNEObject | TypeofNEFunction | NEUndefined, // Masks OrFactsMask = TypeofEQFunction | TypeofNEObject, @@ -27477,7 +27481,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (flags & TypeFlags.Intersection) { return getIntersectionTypeFacts(type as IntersectionType, callerOnlyNeeds); } - return TypeFacts.UnknownFacts; + return strictNullChecks && flags & TypeFlags.Unknown ? TypeFacts.UnknownStrictFacts : TypeFacts.UnknownFacts; } function getIntersectionTypeFacts(type: IntersectionType, callerOnlyNeeds: TypeFacts): TypeFacts { @@ -33699,7 +33703,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } error( node, - facts & TypeFacts.IsUndefined ? facts & TypeFacts.IsNull ? + facts & TypeFacts.IsPossiblyUndefined ? facts & TypeFacts.IsPossiblyNull ? Diagnostics._0_is_possibly_null_or_undefined : Diagnostics._0_is_possibly_undefined : Diagnostics._0_is_possibly_null, @@ -33709,7 +33713,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else { error( node, - facts & TypeFacts.IsUndefined ? facts & TypeFacts.IsNull ? + facts & TypeFacts.IsPossiblyUndefined ? facts & TypeFacts.IsPossiblyNull ? Diagnostics.Object_is_possibly_null_or_undefined : Diagnostics.Object_is_possibly_undefined : Diagnostics.Object_is_possibly_null, @@ -33720,7 +33724,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function reportCannotInvokePossiblyNullOrUndefinedError(node: Node, facts: TypeFacts) { error( node, - facts & TypeFacts.IsUndefined ? facts & TypeFacts.IsNull ? + facts & TypeFacts.IsPossiblyUndefined ? facts & TypeFacts.IsPossiblyNull ? Diagnostics.Cannot_invoke_an_object_which_is_possibly_null_or_undefined : Diagnostics.Cannot_invoke_an_object_which_is_possibly_undefined : Diagnostics.Cannot_invoke_an_object_which_is_possibly_null, @@ -33743,8 +33747,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { error(node, Diagnostics.Object_is_of_type_unknown); return errorType; } - const facts = getTypeFacts(type, TypeFacts.IsUndefinedOrNull); - if (facts & TypeFacts.IsUndefinedOrNull) { + const facts = getTypeFacts(type, TypeFacts.IsPossiblyUndefinedOrNull); + if (facts & TypeFacts.IsPossiblyUndefinedOrNull) { reportError(node, facts); const t = getNonNullableType(type); return t.flags & (TypeFlags.Nullable | TypeFlags.Never) ? errorType : t;