Merge pull request #18438 from Microsoft/unionIntersectionUnit

Remove empty intersection types in unit types
This commit is contained in:
Anders Hejlsberg
2017-09-14 18:44:02 +01:00
committed by GitHub
11 changed files with 413 additions and 10 deletions

View File

@@ -7298,6 +7298,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) {
@@ -7311,7 +7327,11 @@ namespace ts {
if (flags & TypeFlags.Null) typeSet.containsNull = true;
if (!(flags & TypeFlags.ContainsWideningType)) typeSet.containsNonWideningType = true;
}
else if (!(flags & TypeFlags.Never)) {
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
// easier to reason about their origin.
if (flags & TypeFlags.String) typeSet.containsString = true;
if (flags & TypeFlags.Number) typeSet.containsNumber = true;
if (flags & TypeFlags.StringOrNumberLiteral) typeSet.containsStringOrNumberLiteral = true;
@@ -10048,7 +10068,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

@@ -3216,6 +3216,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,