Skip to content

Commit 1858810

Browse files
committed
Preserve order in intersection types
1 parent c623e6c commit 1858810

File tree

1 file changed

+38
-38
lines changed

1 file changed

+38
-38
lines changed

src/compiler/checker.ts

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1539,8 +1539,8 @@ namespace ts {
15391539
else if (type.flags & TypeFlags.Tuple) {
15401540
writeTupleType(<TupleType>type);
15411541
}
1542-
else if (type.flags & (TypeFlags.Union | TypeFlags.Intersection)) {
1543-
writeUnionOrIntersectionType(<UnionType>type, flags);
1542+
else if (type.flags & TypeFlags.UnionOrIntersection) {
1543+
writeUnionOrIntersectionType(<UnionOrIntersectionType>type, flags);
15441544
}
15451545
else if (type.flags & TypeFlags.Anonymous) {
15461546
writeAnonymousType(<ObjectType>type, flags);
@@ -3143,7 +3143,7 @@ namespace ts {
31433143
resolveUnionTypeMembers(<UnionType>type);
31443144
}
31453145
else if (type.flags & TypeFlags.Intersection) {
3146-
resolveIntersectionTypeMembers(<UnionType>type);
3146+
resolveIntersectionTypeMembers(<IntersectionType>type);
31473147
}
31483148
else {
31493149
resolveTypeReferenceMembers(<TypeReference>type);
@@ -3299,7 +3299,7 @@ namespace ts {
32993299
return getPropertyOfObjectType(globalObjectType, name);
33003300
}
33013301
if (type.flags & TypeFlags.UnionOrIntersection) {
3302-
return getPropertyOfUnionOrIntersectionType(<UnionType>type, name);
3302+
return getPropertyOfUnionOrIntersectionType(<UnionOrIntersectionType>type, name);
33033303
}
33043304
return undefined;
33053305
}
@@ -3864,28 +3864,25 @@ namespace ts {
38643864
return links.resolvedType;
38653865
}
38663866

3867-
function addTypeToSortedSet(sortedSet: Type[], type: Type, typeKind: TypeFlags) {
3867+
function addTypeToSet(typeSet: Type[], type: Type, typeKind: TypeFlags) {
38683868
if (type.flags & typeKind) {
3869-
addTypesToSortedSet(sortedSet, (<UnionOrIntersectionType>type).types, typeKind);
3869+
addTypesToSet(typeSet, (<UnionOrIntersectionType>type).types, typeKind);
38703870
}
3871-
else {
3872-
let i = 0;
3873-
let id = type.id;
3874-
while (i < sortedSet.length && sortedSet[i].id < id) {
3875-
i++;
3876-
}
3877-
if (i === sortedSet.length || sortedSet[i].id !== id) {
3878-
sortedSet.splice(i, 0, type);
3879-
}
3871+
else if (!contains(typeSet, type)) {
3872+
typeSet.push(type);
38803873
}
38813874
}
38823875

3883-
function addTypesToSortedSet(sortedTypes: Type[], types: Type[], typeKind: TypeFlags) {
3876+
function addTypesToSet(typeSet: Type[], types: Type[], typeKind: TypeFlags) {
38843877
for (let type of types) {
3885-
addTypeToSortedSet(sortedTypes, type, typeKind);
3878+
addTypeToSet(typeSet, type, typeKind);
38863879
}
38873880
}
38883881

3882+
function compareTypeIds(type1: Type, type2: Type): number {
3883+
return type1.id - type2.id;
3884+
}
3885+
38893886
function isSubtypeOfAny(candidate: Type, types: Type[]): boolean {
38903887
for (let type of types) {
38913888
if (candidate !== type && isTypeSubtypeOf(candidate, type)) {
@@ -3932,26 +3929,27 @@ namespace ts {
39323929
if (types.length === 0) {
39333930
return emptyObjectType;
39343931
}
3935-
let sortedTypes: Type[] = [];
3936-
addTypesToSortedSet(sortedTypes, types, TypeFlags.Union);
3932+
let typeSet: Type[] = [];
3933+
addTypesToSet(typeSet, types, TypeFlags.Union);
3934+
typeSet.sort(compareTypeIds);
39373935
if (noSubtypeReduction) {
3938-
if (containsTypeAny(sortedTypes)) {
3936+
if (containsTypeAny(typeSet)) {
39393937
return anyType;
39403938
}
3941-
removeAllButLast(sortedTypes, undefinedType);
3942-
removeAllButLast(sortedTypes, nullType);
3939+
removeAllButLast(typeSet, undefinedType);
3940+
removeAllButLast(typeSet, nullType);
39433941
}
39443942
else {
3945-
removeSubtypes(sortedTypes);
3943+
removeSubtypes(typeSet);
39463944
}
3947-
if (sortedTypes.length === 1) {
3948-
return sortedTypes[0];
3945+
if (typeSet.length === 1) {
3946+
return typeSet[0];
39493947
}
3950-
let id = getTypeListId(sortedTypes);
3948+
let id = getTypeListId(typeSet);
39513949
let type = unionTypes[id];
39523950
if (!type) {
3953-
type = unionTypes[id] = <UnionType>createObjectType(TypeFlags.Union | getWideningFlagsOfTypes(sortedTypes));
3954-
type.types = sortedTypes;
3951+
type = unionTypes[id] = <UnionType>createObjectType(TypeFlags.Union | getWideningFlagsOfTypes(typeSet));
3952+
type.types = typeSet;
39553953
type.reducedType = noSubtypeReduction ? undefined : type;
39563954
}
39573955
return type;
@@ -3986,20 +3984,22 @@ namespace ts {
39863984
// We do not perform supertype reduction on intersection types. Intersection types are created only by the &
39873985
// type operator and we can't reduce those because we want to support recursive intersection types. For example,
39883986
// a type alias of the form "type List<T> = T & { next: List<T> }" cannot be reduced during its declaration.
3987+
// Also, unlike union types, the order of the constituent types is preserved in order that overload resolution
3988+
// for intersections of types with signatues can be deterministic.
39893989
function getIntersectionType(types: Type[]): Type {
3990-
let sortedTypes: Type[] = [];
3991-
addTypesToSortedSet(sortedTypes, types, TypeFlags.Intersection);
3992-
if (containsTypeAny(sortedTypes)) {
3990+
let typeSet: Type[] = [];
3991+
addTypesToSet(typeSet, types, TypeFlags.Intersection);
3992+
if (containsTypeAny(typeSet)) {
39933993
return anyType;
39943994
}
3995-
if (sortedTypes.length === 1) {
3996-
return sortedTypes[0];
3995+
if (typeSet.length === 1) {
3996+
return typeSet[0];
39973997
}
3998-
let id = getTypeListId(sortedTypes);
3998+
let id = getTypeListId(typeSet);
39993999
let type = intersectionTypes[id];
40004000
if (!type) {
4001-
type = intersectionTypes[id] = <IntersectionType>createObjectType(TypeFlags.Intersection | getWideningFlagsOfTypes(sortedTypes));
4002-
type.types = sortedTypes;
4001+
type = intersectionTypes[id] = <IntersectionType>createObjectType(TypeFlags.Intersection | getWideningFlagsOfTypes(typeSet));
4002+
type.types = typeSet;
40034003
}
40044004
return type;
40054005
}
@@ -8128,7 +8128,7 @@ namespace ts {
81288128
return true;
81298129
}
81308130
if (type.flags & TypeFlags.UnionOrIntersection) {
8131-
let types = (<UnionType>type).types;
8131+
let types = (<UnionOrIntersectionType>type).types;
81328132
for (let current of types) {
81338133
if (current.flags & kind) {
81348134
return true;
@@ -8145,7 +8145,7 @@ namespace ts {
81458145
return true;
81468146
}
81478147
if (type.flags & TypeFlags.UnionOrIntersection) {
8148-
let types = (<UnionType>type).types;
8148+
let types = (<UnionOrIntersectionType>type).types;
81498149
for (let current of types) {
81508150
if (!(current.flags & kind)) {
81518151
return false;

0 commit comments

Comments
 (0)