@@ -9522,44 +9522,13 @@ namespace ts {
9522
9522
return false;
9523
9523
}
9524
9524
9525
- // Return true if the given intersection type contains
9526
- // more than one unit type or,
9527
- // an object type and a nullable type (null or undefined), or
9528
- // a string-like type and a type known to be non-string-like, or
9529
- // a number-like type and a type known to be non-number-like, or
9530
- // a symbol-like type and a type known to be non-symbol-like, or
9531
- // a void-like type and a type known to be non-void-like, or
9532
- // a non-primitive type and a type known to be primitive.
9533
- function isEmptyIntersectionType(type: IntersectionType) {
9534
- let combined: TypeFlags = 0;
9535
- for (const t of type.types) {
9536
- if (t.flags & TypeFlags.Unit && combined & TypeFlags.Unit) {
9537
- return true;
9538
- }
9539
- combined |= t.flags;
9540
- if (combined & TypeFlags.Nullable && combined & (TypeFlags.Object | TypeFlags.NonPrimitive) ||
9541
- combined & TypeFlags.NonPrimitive && combined & (TypeFlags.DisjointDomains & ~TypeFlags.NonPrimitive) ||
9542
- combined & TypeFlags.StringLike && combined & (TypeFlags.DisjointDomains & ~TypeFlags.StringLike) ||
9543
- combined & TypeFlags.NumberLike && combined & (TypeFlags.DisjointDomains & ~TypeFlags.NumberLike) ||
9544
- combined & TypeFlags.BigIntLike && combined & (TypeFlags.DisjointDomains & ~TypeFlags.BigIntLike) ||
9545
- combined & TypeFlags.ESSymbolLike && combined & (TypeFlags.DisjointDomains & ~TypeFlags.ESSymbolLike) ||
9546
- combined & TypeFlags.VoidLike && combined & (TypeFlags.DisjointDomains & ~TypeFlags.VoidLike)) {
9547
- return true;
9548
- }
9549
- }
9550
- return false;
9551
- }
9552
-
9553
9525
function addTypeToUnion(typeSet: Type[], includes: TypeFlags, type: Type) {
9554
9526
const flags = type.flags;
9555
9527
if (flags & TypeFlags.Union) {
9556
9528
return addTypesToUnion(typeSet, includes, (<UnionType>type).types);
9557
9529
}
9558
- // We ignore 'never' types in unions. Likewise, we ignore intersections of unit types as they are
9559
- // another form of 'never' (in that they have an empty value domain). We could in theory turn
9560
- // intersections of unit types into 'never' upon construction, but deferring the reduction makes it
9561
- // easier to reason about their origin.
9562
- if (!(flags & TypeFlags.Never || flags & TypeFlags.Intersection && isEmptyIntersectionType(<IntersectionType>type))) {
9530
+ // We ignore 'never' types in unions
9531
+ if (!(flags & TypeFlags.Never)) {
9563
9532
includes |= flags & TypeFlags.IncludesMask;
9564
9533
if (flags & TypeFlags.StructuredOrInstantiable) includes |= TypeFlags.IncludesStructuredOrInstantiable;
9565
9534
if (type === wildcardType) includes |= TypeFlags.IncludesWildcard;
@@ -9783,13 +9752,18 @@ namespace ts {
9783
9752
}
9784
9753
}
9785
9754
else {
9786
- includes |= flags & TypeFlags.IncludesMask;
9787
9755
if (flags & TypeFlags.AnyOrUnknown) {
9788
9756
if (type === wildcardType) includes |= TypeFlags.IncludesWildcard;
9789
9757
}
9790
9758
else if ((strictNullChecks || !(flags & TypeFlags.Nullable)) && !contains(typeSet, type)) {
9759
+ if (type.flags & TypeFlags.Unit && includes & TypeFlags.Unit) {
9760
+ // We have seen two distinct unit types which means we should reduce to an
9761
+ // empty intersection. Adding TypeFlags.NonPrimitive causes that to happen.
9762
+ includes |= TypeFlags.NonPrimitive;
9763
+ }
9791
9764
typeSet.push(type);
9792
9765
}
9766
+ includes |= flags & TypeFlags.IncludesMask;
9793
9767
}
9794
9768
return includes;
9795
9769
}
@@ -9905,7 +9879,23 @@ namespace ts {
9905
9879
function getIntersectionType(types: ReadonlyArray<Type>, aliasSymbol?: Symbol, aliasTypeArguments?: ReadonlyArray<Type>): Type {
9906
9880
const typeSet: Type[] = [];
9907
9881
const includes = addTypesToIntersection(typeSet, 0, types);
9908
- if (includes & TypeFlags.Never) {
9882
+ // An intersection type is considered empty if it contains
9883
+ // the type never, or
9884
+ // more than one unit type or,
9885
+ // an object type and a nullable type (null or undefined), or
9886
+ // a string-like type and a type known to be non-string-like, or
9887
+ // a number-like type and a type known to be non-number-like, or
9888
+ // a symbol-like type and a type known to be non-symbol-like, or
9889
+ // a void-like type and a type known to be non-void-like, or
9890
+ // a non-primitive type and a type known to be primitive.
9891
+ if (includes & TypeFlags.Never ||
9892
+ strictNullChecks && includes & TypeFlags.Nullable && includes & (TypeFlags.Object | TypeFlags.NonPrimitive | TypeFlags.IncludesEmptyObject) ||
9893
+ includes & TypeFlags.NonPrimitive && includes & (TypeFlags.DisjointDomains & ~TypeFlags.NonPrimitive) ||
9894
+ includes & TypeFlags.StringLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.StringLike) ||
9895
+ includes & TypeFlags.NumberLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.NumberLike) ||
9896
+ includes & TypeFlags.BigIntLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.BigIntLike) ||
9897
+ includes & TypeFlags.ESSymbolLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.ESSymbolLike) ||
9898
+ includes & TypeFlags.VoidLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.VoidLike)) {
9909
9899
return neverType;
9910
9900
}
9911
9901
if (includes & TypeFlags.Any) {
0 commit comments