diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d8ca648fdf3..328f3710029 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8428,10 +8428,6 @@ namespace ts { return links.resolvedType; } - function isGenericExtendsType(type: Type) { - return maybeTypeOfKind(type, TypeFlags.Instantiable | TypeFlags.GenericMappedType); - } - function createExtendsType(checkType: Type, extendsType: Type) { const type = createType(TypeFlags.Extends); type.checkType = checkType; @@ -8447,9 +8443,16 @@ namespace ts { if (checkType.flags & TypeFlags.Any) { return booleanType; } - if (!isGenericExtendsType(checkType) && !isGenericExtendsType(extendsType)) { - return isTypeAssignableTo(checkType, extendsType) ? trueType : falseType; + // Return trueType if type is definitely assignable + if (isTypeAssignableTo(checkType, extendsType)) { + return trueType; } + // Return falseType is type is definitely not assignable + if (!isTypeAssignableTo(instantiateType(checkType, anyMapper), instantiateType(extendsType, constraintMapper))) { + // Type is definitely not assignable + return falseType; + } + // Type is possibly assignable, defer the check const id = checkType.id + "," + extendsType.id; let type = extendsTypes.get(id); if (!type) { @@ -8844,6 +8847,14 @@ namespace ts { return t => t === source ? target : baseMapper(t); } + function anyMapper(type: Type) { + return type.flags & TypeFlags.TypeParameter ? anyType : type; + } + + function constraintMapper(type: Type) { + return type.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(type) || anyType : type; + } + function cloneTypeParameter(typeParameter: TypeParameter): TypeParameter { const result = createType(TypeFlags.TypeParameter); result.symbol = typeParameter.symbol;