From 7e07eef8bb9860cf6ac0a19956a4af1e903229dc Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 13 Sep 2018 17:49:09 -0700 Subject: [PATCH] Try to find object/intersection types with the most overlap when failing assignability against unions. --- src/compiler/checker.ts | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6ef51bc401a..8b1c9c3eae2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11921,7 +11921,8 @@ namespace ts { findMatchingDiscriminantType(source, target) || findMatchingTypeReferenceOrTypeAliasReference(source, target) || findBestTypeForObjectLiteral(source, target) || - findBestTypeForInvokable(source, target); + findBestTypeForInvokable(source, target) || + findMostOverlappyType(source, target); isRelatedTo(source, bestMatchingType || targetTypes[targetTypes.length - 1], /*reportErrors*/ true); } @@ -11961,6 +11962,32 @@ namespace ts { } } + function findMostOverlappyType(source: Type, unionTarget: UnionOrIntersectionType) { + if (!(source.flags & (TypeFlags.Object | TypeFlags.Intersection))) { + return undefined; + } + const sourceProperties = getPropertiesOfType(source); + let bestType; + let count = -1; + for (const target of unionTarget.types) { + if (!(target.flags & (TypeFlags.Object | TypeFlags.Intersection))) { + continue; + } + + let currentCount = 0; + for (const prop of sourceProperties) { + if (getPropertyOfType(target, prop.escapedName)) { + currentCount++; + } + } + if (currentCount >= count) { + count = currentCount; + bestType = target; + } + } + return bestType; + } + // Keep this up-to-date with the same logic within `getApparentTypeOfContextualType`, since they should behave similarly function findMatchingDiscriminantType(source: Type, target: Type) { if (target.flags & TypeFlags.Union) {