From a04ecb592c91c1b68e4893174ae420f21a6f3492 Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 22 May 2020 00:40:28 +0000 Subject: [PATCH] Check constraints deeply on singleton types. --- src/compiler/checker.ts | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 734fb738dfe..5f1e95dbce3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15764,23 +15764,13 @@ namespace ts { } } - if (isLiteralType(source) && !typeCouldHaveNoTopLevelSingletonTypes(target)) { + if (isLiteralType(source) && !typeCouldHaveTopLevelSingletonTypes(target)) { generalizedSourceType = getTypeNameForErrorDisplay(getBaseTypeOfLiteralType(source)); } reportError(message, generalizedSourceType, targetType); } - function typeCouldHaveNoTopLevelSingletonTypes(type: Type) { - return forEachType(type, typeCouldHaveNoTopLevelSingletonTypesWorker); - } - - function typeCouldHaveNoTopLevelSingletonTypesWorker(type: Type): boolean { - return (type.flags & TypeFlags.Intersection) - ? !!forEach((type as IntersectionType).types, typeCouldHaveNoTopLevelSingletonTypesWorker) - : isUnitType(type) || !!(type.flags & TypeFlags.Instantiable); - } - function tryElaborateErrorsForPrimitivesAndObjects(source: Type, target: Type) { const sourceType = symbolValueDeclarationIsContextSensitive(source.symbol) ? typeToString(source, source.symbol.valueDeclaration) : typeToString(source); const targetType = symbolValueDeclarationIsContextSensitive(target.symbol) ? typeToString(target, target.symbol.valueDeclaration) : typeToString(target); @@ -17375,6 +17365,21 @@ namespace ts { } } + function typeCouldHaveTopLevelSingletonTypes(type: Type): boolean { + if (type.flags & TypeFlags.UnionOrIntersection) { + return !!forEach((type as IntersectionType).types, typeCouldHaveTopLevelSingletonTypes); + } + + if (type.flags & TypeFlags.Instantiable) { + const constraint = getConstraintOfType(type); + if (constraint) { + return typeCouldHaveTopLevelSingletonTypes(constraint); + } + } + + return isUnitType(type); + } + function getBestMatchingType(source: Type, target: UnionOrIntersectionType, isRelatedTo = compareTypesAssignable) { return findMatchingDiscriminantType(source, target, isRelatedTo, /*skipPartial*/ true) || findMatchingTypeReferenceOrTypeAliasReference(source, target) ||