@@ -1539,8 +1539,8 @@ namespace ts {
1539
1539
else if (type.flags & TypeFlags.Tuple) {
1540
1540
writeTupleType(<TupleType>type);
1541
1541
}
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);
1544
1544
}
1545
1545
else if (type.flags & TypeFlags.Anonymous) {
1546
1546
writeAnonymousType(<ObjectType>type, flags);
@@ -3143,7 +3143,7 @@ namespace ts {
3143
3143
resolveUnionTypeMembers(<UnionType>type);
3144
3144
}
3145
3145
else if (type.flags & TypeFlags.Intersection) {
3146
- resolveIntersectionTypeMembers(<UnionType >type);
3146
+ resolveIntersectionTypeMembers(<IntersectionType >type);
3147
3147
}
3148
3148
else {
3149
3149
resolveTypeReferenceMembers(<TypeReference>type);
@@ -3299,7 +3299,7 @@ namespace ts {
3299
3299
return getPropertyOfObjectType(globalObjectType, name);
3300
3300
}
3301
3301
if (type.flags & TypeFlags.UnionOrIntersection) {
3302
- return getPropertyOfUnionOrIntersectionType(<UnionType >type, name);
3302
+ return getPropertyOfUnionOrIntersectionType(<UnionOrIntersectionType >type, name);
3303
3303
}
3304
3304
return undefined;
3305
3305
}
@@ -3864,28 +3864,25 @@ namespace ts {
3864
3864
return links.resolvedType;
3865
3865
}
3866
3866
3867
- function addTypeToSortedSet(sortedSet : Type[], type: Type, typeKind: TypeFlags) {
3867
+ function addTypeToSet(typeSet : Type[], type: Type, typeKind: TypeFlags) {
3868
3868
if (type.flags & typeKind) {
3869
- addTypesToSortedSet(sortedSet , (<UnionOrIntersectionType>type).types, typeKind);
3869
+ addTypesToSet(typeSet , (<UnionOrIntersectionType>type).types, typeKind);
3870
3870
}
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);
3880
3873
}
3881
3874
}
3882
3875
3883
- function addTypesToSortedSet(sortedTypes : Type[], types: Type[], typeKind: TypeFlags) {
3876
+ function addTypesToSet(typeSet : Type[], types: Type[], typeKind: TypeFlags) {
3884
3877
for (let type of types) {
3885
- addTypeToSortedSet(sortedTypes , type, typeKind);
3878
+ addTypeToSet(typeSet , type, typeKind);
3886
3879
}
3887
3880
}
3888
3881
3882
+ function compareTypeIds(type1: Type, type2: Type): number {
3883
+ return type1.id - type2.id;
3884
+ }
3885
+
3889
3886
function isSubtypeOfAny(candidate: Type, types: Type[]): boolean {
3890
3887
for (let type of types) {
3891
3888
if (candidate !== type && isTypeSubtypeOf(candidate, type)) {
@@ -3932,26 +3929,27 @@ namespace ts {
3932
3929
if (types.length === 0) {
3933
3930
return emptyObjectType;
3934
3931
}
3935
- let sortedTypes: Type[] = [];
3936
- addTypesToSortedSet(sortedTypes, types, TypeFlags.Union);
3932
+ let typeSet: Type[] = [];
3933
+ addTypesToSet(typeSet, types, TypeFlags.Union);
3934
+ typeSet.sort(compareTypeIds);
3937
3935
if (noSubtypeReduction) {
3938
- if (containsTypeAny(sortedTypes )) {
3936
+ if (containsTypeAny(typeSet )) {
3939
3937
return anyType;
3940
3938
}
3941
- removeAllButLast(sortedTypes , undefinedType);
3942
- removeAllButLast(sortedTypes , nullType);
3939
+ removeAllButLast(typeSet , undefinedType);
3940
+ removeAllButLast(typeSet , nullType);
3943
3941
}
3944
3942
else {
3945
- removeSubtypes(sortedTypes );
3943
+ removeSubtypes(typeSet );
3946
3944
}
3947
- if (sortedTypes .length === 1) {
3948
- return sortedTypes [0];
3945
+ if (typeSet .length === 1) {
3946
+ return typeSet [0];
3949
3947
}
3950
- let id = getTypeListId(sortedTypes );
3948
+ let id = getTypeListId(typeSet );
3951
3949
let type = unionTypes[id];
3952
3950
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 ;
3955
3953
type.reducedType = noSubtypeReduction ? undefined : type;
3956
3954
}
3957
3955
return type;
@@ -3986,20 +3984,22 @@ namespace ts {
3986
3984
// We do not perform supertype reduction on intersection types. Intersection types are created only by the &
3987
3985
// type operator and we can't reduce those because we want to support recursive intersection types. For example,
3988
3986
// 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.
3989
3989
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 )) {
3993
3993
return anyType;
3994
3994
}
3995
- if (sortedTypes .length === 1) {
3996
- return sortedTypes [0];
3995
+ if (typeSet .length === 1) {
3996
+ return typeSet [0];
3997
3997
}
3998
- let id = getTypeListId(sortedTypes );
3998
+ let id = getTypeListId(typeSet );
3999
3999
let type = intersectionTypes[id];
4000
4000
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 ;
4003
4003
}
4004
4004
return type;
4005
4005
}
@@ -8128,7 +8128,7 @@ namespace ts {
8128
8128
return true;
8129
8129
}
8130
8130
if (type.flags & TypeFlags.UnionOrIntersection) {
8131
- let types = (<UnionType >type).types;
8131
+ let types = (<UnionOrIntersectionType >type).types;
8132
8132
for (let current of types) {
8133
8133
if (current.flags & kind) {
8134
8134
return true;
@@ -8145,7 +8145,7 @@ namespace ts {
8145
8145
return true;
8146
8146
}
8147
8147
if (type.flags & TypeFlags.UnionOrIntersection) {
8148
- let types = (<UnionType >type).types;
8148
+ let types = (<UnionOrIntersectionType >type).types;
8149
8149
for (let current of types) {
8150
8150
if (!(current.flags & kind)) {
8151
8151
return false;
0 commit comments