diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 580d2a1aee2..bf37de96ae2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8328,8 +8328,11 @@ namespace ts { !t.numberIndexInfo; } - function isEmptyObjectType(type: Type) { - return type.flags & TypeFlags.Object && isEmptyResolvedType(resolveStructuredTypeMembers(type)); + function isEmptyObjectType(type: Type): boolean { + return type.flags & TypeFlags.Object ? isEmptyResolvedType(resolveStructuredTypeMembers(type)) : + type.flags & TypeFlags.Union ? forEach((type).types, isEmptyObjectType) : + type.flags & TypeFlags.Intersection ? !forEach((type).types, t => !isEmptyObjectType(t)) : + false; } function isEnumTypeRelatedTo(source: EnumType, target: EnumType, errorReporter?: ErrorReporter) { @@ -8645,14 +8648,8 @@ namespace ts { function isKnownProperty(type: Type, name: string, isComparingJsxAttributes: boolean): boolean { if (type.flags & TypeFlags.Object) { const resolved = resolveStructuredTypeMembers(type); - if ((relation === assignableRelation || relation === comparableRelation) && - (type === globalObjectType || (!isComparingJsxAttributes && isEmptyObjectType(resolved)))) { - return true; - } - else if (resolved.stringIndexInfo || (resolved.numberIndexInfo && isNumericLiteralName(name))) { - return true; - } - else if (getPropertyOfType(type, name) || (isComparingJsxAttributes && !isUnhyphenatedJsxName(name))) { + if (resolved.stringIndexInfo || resolved.numberIndexInfo && isNumericLiteralName(name) || + getPropertyOfType(type, name) || isComparingJsxAttributes && !isUnhyphenatedJsxName(name)) { // For JSXAttributes, if the attribute has a hyphenated name, consider that the attribute to be known. return true; } @@ -8670,6 +8667,10 @@ namespace ts { function hasExcessProperties(source: FreshObjectLiteralType, target: Type, reportErrors: boolean): boolean { if (maybeTypeOfKind(target, TypeFlags.Object) && !(getObjectFlags(target) & ObjectFlags.ObjectLiteralPatternWithComputedProperties)) { const isComparingJsxAttributes = !!(source.flags & TypeFlags.JsxAttributes); + if ((relation === assignableRelation || relation === comparableRelation) && + (target === globalObjectType || (!isComparingJsxAttributes && isEmptyObjectType(target)))) { + return false; + } for (const prop of getPropertiesOfObjectType(source)) { if (!isKnownProperty(target, prop.name, isComparingJsxAttributes)) { if (reportErrors) {