@@ -11959,29 +11959,31 @@ namespace ts {
11959
11959
}
11960
11960
11961
11961
function findMostOverlappyType(source: Type, unionTarget: UnionOrIntersectionType) {
11962
- if (!(source.flags & (TypeFlags.Object | TypeFlags.Intersection))) {
11963
- return undefined;
11964
- }
11965
- const sourceProperties = getPropertiesOfType(source);
11966
- let bestType;
11967
- let count = -1;
11962
+ let bestMatch: Type | undefined;
11963
+ let matchingCount = 0;
11968
11964
for (const target of unionTarget.types) {
11969
- if (!(target.flags & (TypeFlags.Object | TypeFlags.Intersection))) {
11970
- continue;
11965
+ const overlap = getIntersectionType([getIndexType(source), getIndexType(target)]);
11966
+ if (overlap.flags & TypeFlags.Index) {
11967
+ // perfect overlap of keys
11968
+ bestMatch = target;
11969
+ matchingCount = Infinity;
11971
11970
}
11972
-
11973
- let currentCount = 0;
11974
- for (const prop of sourceProperties) {
11975
- if (getPropertyOfType(target, prop.escapedName)) {
11976
- currentCount++;
11971
+ else if (overlap.flags & TypeFlags.Union) {
11972
+ // Some subset overlap if we have only string literals.
11973
+ // If we have a union of index types, it seems likely that we
11974
+ // needed to elaborate between two generic mapped types anyway.
11975
+ const len = length((overlap as UnionType).types);
11976
+ if (len >= matchingCount) {
11977
+ bestMatch = target;
11978
+ matchingCount = len;
11977
11979
}
11978
11980
}
11979
- if (currentCount >= count ) {
11980
- count = currentCount ;
11981
- bestType = target ;
11981
+ else if (!(overlap.flags & TypeFlags.Never) && 1 >= matchingCount ) {
11982
+ bestMatch = target ;
11983
+ matchingCount = 1 ;
11982
11984
}
11983
11985
}
11984
- return bestType ;
11986
+ return bestMatch ;
11985
11987
}
11986
11988
11987
11989
// Keep this up-to-date with the same logic within `getApparentTypeOfContextualType`, since they should behave similarly
0 commit comments