Skip to content

Commit 6a0f729

Browse files
committed
Simplify logic in checkTypeRelatedTo
1 parent eb7d2cb commit 6a0f729

File tree

1 file changed

+25
-32
lines changed

1 file changed

+25
-32
lines changed

src/compiler/checker.ts

Lines changed: 25 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5622,7 +5622,6 @@ namespace ts {
56225622
if (type.flags & TypeFlags.Union) {
56235623
// We are attempting to construct a type of the form X & (A | B) & Y. Transform this into a type of
56245624
// the form X & A & Y | X & B & Y and recursively reduce until no union type constituents remain.
5625-
let unionType = <UnionType>types[i];
56265625
return getUnionType(map((<UnionType>type).types, t => getIntersectionType(replaceElement(types, i, t))),
56275626
/*subtypeReduction*/ false, aliasSymbol, aliasTypeArguments);
56285627
}
@@ -6574,52 +6573,46 @@ namespace ts {
65746573

65756574
const saveErrorInfo = errorInfo;
65766575

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.
65786579
if (source.flags & TypeFlags.Union) {
65796580
if (relation === comparableRelation) {
65806581
result = someTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive));
65816582
}
65826583
else {
65836584
result = eachTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive));
65846585
}
6585-
65866586
if (result) {
65876587
return result;
65886588
}
65896589
}
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))) {
65946592
return result;
65956593
}
65966594
}
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;
66186598
}
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;
66236616
}
66246617
}
66256618

0 commit comments

Comments
 (0)