@@ -11959,29 +11959,31 @@ namespace ts {
1195911959 }
1196011960
1196111961 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;
1196811964 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;
1197111970 }
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;
1197711979 }
1197811980 }
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 ;
1198211984 }
1198311985 }
11984- return bestType ;
11986+ return bestMatch ;
1198511987 }
1198611988
1198711989 // Keep this up-to-date with the same logic within `getApparentTypeOfContextualType`, since they should behave similarly
0 commit comments