Remove intersections of object and nullable types from union types

This commit is contained in:
Anders Hejlsberg
2017-09-13 11:52:10 -07:00
parent 78f4cbe53c
commit c64beb90df
2 changed files with 19 additions and 2 deletions

View File

@@ -7289,6 +7289,22 @@ namespace ts {
return binarySearchTypes(types, type) >= 0;
}
// Return true if the given intersection type contains (a) more than one unit type or (b) an object
// type and a nullable type (null or undefined).
function isEmptyIntersectionType(type: IntersectionType) {
let combined: TypeFlags = 0;
for (const t of type.types) {
if (t.flags & TypeFlags.Unit && combined & TypeFlags.Unit) {
return true;
}
combined |= t.flags;
if (combined & TypeFlags.Nullable && combined & (TypeFlags.Object | TypeFlags.NonPrimitive)) {
return true;
}
}
return false;
}
function addTypeToUnion(typeSet: TypeSet, type: Type) {
const flags = type.flags;
if (flags & TypeFlags.Union) {
@@ -7302,7 +7318,7 @@ namespace ts {
if (flags & TypeFlags.Null) typeSet.containsNull = true;
if (!(flags & TypeFlags.ContainsWideningType)) typeSet.containsNonWideningType = true;
}
else if (!(flags & TypeFlags.Never || flags & TypeFlags.Intersection && every((<IntersectionType>type).types, isUnitType))) {
else if (!(flags & TypeFlags.Never || flags & TypeFlags.Intersection && isEmptyIntersectionType(<IntersectionType>type))) {
// We ignore 'never' types in unions. Likewise, we ignore intersections of unit types as they are
// another form of 'never' (in that they have an empty value domain). We could in theory turn
// intersections of unit types into 'never' upon construction, but deferring the reduction makes it
@@ -10041,7 +10057,7 @@ namespace ts {
}
function isUnitType(type: Type): boolean {
return (type.flags & (TypeFlags.Literal | TypeFlags.Undefined | TypeFlags.Null)) !== 0;
return !!(type.flags & TypeFlags.Unit);
}
function isLiteralType(type: Type): boolean {

View File

@@ -3217,6 +3217,7 @@ namespace ts {
/* @internal */
Nullable = Undefined | Null,
Literal = StringLiteral | NumberLiteral | BooleanLiteral,
Unit = Literal | Nullable,
StringOrNumberLiteral = StringLiteral | NumberLiteral,
/* @internal */
DefinitelyFalsy = StringLiteral | NumberLiteral | BooleanLiteral | Void | Undefined | Null,