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