Skip to content

Commit 30d15a8

Browse files
committed
Addressing CR feedback
1 parent fb1bf42 commit 30d15a8

File tree

1 file changed

+26
-12
lines changed

1 file changed

+26
-12
lines changed

src/compiler/checker.ts

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3910,25 +3910,23 @@ namespace ts {
39103910
return links.resolvedType;
39113911
}
39123912

3913-
function addTypeToSet(typeSet: Type[], type: Type, typeKind: TypeFlags) {
3914-
if (type.flags & typeKind) {
3915-
addTypesToSet(typeSet, (<UnionOrIntersectionType>type).types, typeKind);
3913+
function addTypeToSet(typeSet: Type[], type: Type, typeSetKind: TypeFlags) {
3914+
if (type.flags & typeSetKind) {
3915+
addTypesToSet(typeSet, (<UnionOrIntersectionType>type).types, typeSetKind);
39163916
}
39173917
else if (!contains(typeSet, type)) {
39183918
typeSet.push(type);
39193919
}
39203920
}
39213921

3922-
function addTypesToSet(typeSet: Type[], types: Type[], typeKind: TypeFlags) {
3922+
// Add the given types to the given type set. Order is preserved, duplicates are removed,
3923+
// and nested types of the given kind are flattened into the set.
3924+
function addTypesToSet(typeSet: Type[], types: Type[], typeSetKind: TypeFlags) {
39233925
for (let type of types) {
3924-
addTypeToSet(typeSet, type, typeKind);
3926+
addTypeToSet(typeSet, type, typeSetKind);
39253927
}
39263928
}
39273929

3928-
function compareTypeIds(type1: Type, type2: Type): number {
3929-
return type1.id - type2.id;
3930-
}
3931-
39323930
function isSubtypeOfAny(candidate: Type, types: Type[]): boolean {
39333931
for (let type of types) {
39343932
if (candidate !== type && isTypeSubtypeOf(candidate, type)) {
@@ -3967,6 +3965,10 @@ namespace ts {
39673965
}
39683966
}
39693967

3968+
function compareTypeIds(type1: Type, type2: Type): number {
3969+
return type1.id - type2.id;
3970+
}
3971+
39703972
// The noSubtypeReduction flag is there because it isn't possible to always do subtype reduction. The flag
39713973
// is true when creating a union type from a type node and when instantiating a union type. In both of those
39723974
// cases subtype reduction has to be deferred to properly support recursive union types. For example, a
@@ -4031,8 +4033,11 @@ namespace ts {
40314033
// type operator and we can't reduce those because we want to support recursive intersection types. For example,
40324034
// a type alias of the form "type List<T> = T & { next: List<T> }" cannot be reduced during its declaration.
40334035
// Also, unlike union types, the order of the constituent types is preserved in order that overload resolution
4034-
// for intersections of types with signatues can be deterministic.
4036+
// for intersections of types with signatures can be deterministic.
40354037
function getIntersectionType(types: Type[]): Type {
4038+
if (types.length === 0) {
4039+
return emptyObjectType;
4040+
}
40364041
let typeSet: Type[] = [];
40374042
addTypesToSet(typeSet, types, TypeFlags.Intersection);
40384043
if (containsTypeAny(typeSet)) {
@@ -4469,6 +4474,7 @@ namespace ts {
44694474
}
44704475
}
44714476
else if (relation !== identityRelation) {
4477+
// Note that the "each" checks must precede the "some" checks to produce the correct results
44724478
if (source.flags & TypeFlags.Union) {
44734479
if (result = eachTypeRelatedToType(<UnionType>source, target, reportErrors)) {
44744480
return result;
@@ -4480,6 +4486,9 @@ namespace ts {
44804486
}
44814487
}
44824488
else {
4489+
// A check of the form A | B = C & D can be satisfied either by having C be related to A | B,
4490+
// D be related to A | B, C & D be related to A, or C & D be related to B. Thus, we need to
4491+
// check both sides here.
44834492
if (source.flags & TypeFlags.Intersection) {
44844493
// If target is a union type the following check will report errors so we suppress them here
44854494
if (result = someTypeRelatedToType(<IntersectionType>source, target, reportErrors && !(target.flags & TypeFlags.Union))) {
@@ -4508,8 +4517,11 @@ namespace ts {
45084517
// it may hold in a structural comparison.
45094518
// Report structural errors only if we haven't reported any errors yet
45104519
let reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo;
4511-
// identity relation does not use apparent type
4520+
// Identity relation does not use apparent type
45124521
let sourceOrApparentType = relation === identityRelation ? source : getApparentType(source);
4522+
// In a check of the form X = A & B, we will have previously checked if A relates to X or B relates
4523+
// to X. Failing both of those we want to check if the aggregation of A and B's members structurally
4524+
// relates to X. Thus, we include intersection types on the source side here.
45134525
if (sourceOrApparentType.flags & (TypeFlags.ObjectType | TypeFlags.Intersection) && target.flags & TypeFlags.ObjectType) {
45144526
if (result = objectTypeRelatedTo(sourceOrApparentType, <ObjectType>target, reportStructuralErrors)) {
45154527
errorInfo = saveErrorInfo;
@@ -5423,7 +5435,9 @@ namespace ts {
54235435
}
54245436
}
54255437
// Next, if target is a union type containing a single naked type parameter, make a
5426-
// secondary inference to that type parameter
5438+
// secondary inference to that type parameter. We don't do this for intersection types
5439+
// because in a target type like Foo & T we don't know how which parts of the source type
5440+
// should be matched by Foo and which should be inferred to T.
54275441
if (target.flags & TypeFlags.Union && typeParameterCount === 1) {
54285442
inferiority++;
54295443
inferFromTypes(source, typeParameter);

0 commit comments

Comments
 (0)