Eagerly evaluate S extends T when S is definitely or definitely not assignable to T

This commit is contained in:
Anders Hejlsberg
2018-01-14 14:38:48 -08:00
parent bb23bb2a92
commit c10a5520e2

View File

@@ -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 = <ExtendsType>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(<TypeParameter>type) || anyType : type;
}
function cloneTypeParameter(typeParameter: TypeParameter): TypeParameter {
const result = <TypeParameter>createType(TypeFlags.TypeParameter);
result.symbol = typeParameter.symbol;