@@ -5622,7 +5622,6 @@ namespace ts {
5622
5622
if (type.flags & TypeFlags.Union) {
5623
5623
// We are attempting to construct a type of the form X & (A | B) & Y. Transform this into a type of
5624
5624
// the form X & A & Y | X & B & Y and recursively reduce until no union type constituents remain.
5625
- let unionType = <UnionType>types[i];
5626
5625
return getUnionType(map((<UnionType>type).types, t => getIntersectionType(replaceElement(types, i, t))),
5627
5626
/*subtypeReduction*/ false, aliasSymbol, aliasTypeArguments);
5628
5627
}
@@ -6574,52 +6573,46 @@ namespace ts {
6574
6573
6575
6574
const saveErrorInfo = errorInfo;
6576
6575
6577
- // Note that these checks are specifically ordered to produce correct results.
6576
+ // Note that these checks are specifically ordered to produce correct results. In particular,
6577
+ // we need to deconstruct unions before intersections (because unions are always at the top),
6578
+ // and we need to handle "each" relations before "some" relations for the same kind of type.
6578
6579
if (source.flags & TypeFlags.Union) {
6579
6580
if (relation === comparableRelation) {
6580
6581
result = someTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive));
6581
6582
}
6582
6583
else {
6583
6584
result = eachTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive));
6584
6585
}
6585
-
6586
6586
if (result) {
6587
6587
return result;
6588
6588
}
6589
6589
}
6590
- else if (target.flags & TypeFlags.Intersection) {
6591
- result = typeRelatedToEachType(source, target as IntersectionType, reportErrors);
6592
-
6593
- if (result) {
6590
+ else if (target.flags & TypeFlags.Union) {
6591
+ if (result = typeRelatedToSomeType(source, <UnionType>target, reportErrors && !(source.flags & TypeFlags.Primitive) && !(target.flags & TypeFlags.Primitive))) {
6594
6592
return result;
6595
6593
}
6596
6594
}
6597
- else {
6598
- // It is necessary to try these "some" checks on both sides because there may be nested "each" checks
6599
- // on either side that need to be prioritized. For example, A | B = (A | B) & (C | D) or
6600
- // A & B = (A & B) | (C & D).
6601
- if (source.flags & TypeFlags.Intersection) {
6602
- // Check to see if any constituents of the intersection are immediately related to the target.
6603
- //
6604
- // Don't report errors though. Checking whether a constituent is related to the source is not actually
6605
- // useful and leads to some confusing error messages. Instead it is better to let the below checks
6606
- // take care of this, or to not elaborate at all. For instance,
6607
- //
6608
- // - For an object type (such as 'C = A & B'), users are usually more interested in structural errors.
6609
- //
6610
- // - For a union type (such as '(A | B) = (C & D)'), it's better to hold onto the whole intersection
6611
- // than to report that 'D' is not assignable to 'A' or 'B'.
6612
- //
6613
- // - For a primitive type or type parameter (such as 'number = A & B') there is no point in
6614
- // breaking the intersection apart.
6615
- if (result = someTypeRelatedToType(<IntersectionType>source, target, /*reportErrors*/ false)) {
6616
- return result;
6617
- }
6595
+ else if (target.flags & TypeFlags.Intersection) {
6596
+ if (result = typeRelatedToEachType(source, target as IntersectionType, reportErrors)) {
6597
+ return result;
6618
6598
}
6619
- if (target.flags & TypeFlags.Union) {
6620
- if (result = typeRelatedToSomeType(source, <UnionType>target, reportErrors && !(source.flags & TypeFlags.Primitive) && !(target.flags & TypeFlags.Primitive))) {
6621
- return result;
6622
- }
6599
+ }
6600
+ else if (source.flags & TypeFlags.Intersection) {
6601
+ // Check to see if any constituents of the intersection are immediately related to the target.
6602
+ //
6603
+ // Don't report errors though. Checking whether a constituent is related to the source is not actually
6604
+ // useful and leads to some confusing error messages. Instead it is better to let the below checks
6605
+ // take care of this, or to not elaborate at all. For instance,
6606
+ //
6607
+ // - For an object type (such as 'C = A & B'), users are usually more interested in structural errors.
6608
+ //
6609
+ // - For a union type (such as '(A | B) = (C & D)'), it's better to hold onto the whole intersection
6610
+ // than to report that 'D' is not assignable to 'A' or 'B'.
6611
+ //
6612
+ // - For a primitive type or type parameter (such as 'number = A & B') there is no point in
6613
+ // breaking the intersection apart.
6614
+ if (result = someTypeRelatedToType(<IntersectionType>source, target, /*reportErrors*/ false)) {
6615
+ return result;
6623
6616
}
6624
6617
}
6625
6618
0 commit comments