Improve handling of any as a base type

Also improve how the string indexer for any-inheriting types is added.
This commit is contained in:
Nathan Shively-Sanders 2017-03-29 16:09:33 -07:00
parent f1c1969907
commit 765ac7ccd1

View file

@ -4649,7 +4649,7 @@ namespace ts {
function resolveBaseTypesOfClass(type: InterfaceType): void {
type.resolvedBaseTypes = type.resolvedBaseTypes || emptyArray;
const baseConstructorType = getApparentType(getBaseConstructorTypeOfClass(type));
if (!(baseConstructorType.flags & (TypeFlags.Object | TypeFlags.Intersection))) {
if (!(baseConstructorType.flags & (TypeFlags.Object | TypeFlags.Intersection | TypeFlags.Any))) {
return;
}
const baseTypeNode = getBaseTypeNodeOfClass(type);
@ -4662,6 +4662,9 @@ namespace ts {
// type arguments in the same manner as a type reference to get the same error reporting experience.
baseType = getTypeFromClassOrInterfaceReference(baseTypeNode, baseConstructorType.symbol);
}
else if (baseConstructorType.flags & TypeFlags.Any) {
baseType = anyType;
}
else {
// The class derives from a "class-like" constructor function, check that we have at least one construct signature
// with a matching number of type parameters and use the return type of the first instantiated signature. Elsewhere
@ -4715,10 +4718,11 @@ namespace ts {
return true;
}
// A valid base type is any non-generic object type or intersection of non-generic
// A valid base type is `any`, any non-generic object type or intersection of non-generic
// object types.
function isValidBaseType(type: Type): boolean {
return type.flags & (TypeFlags.Object | TypeFlags.NonPrimitive) && !isGenericMappedType(type) ||
return !!(type.flags & TypeFlags.Any) ||
type.flags & (TypeFlags.Object | TypeFlags.NonPrimitive) && !isGenericMappedType(type) ||
type.flags & TypeFlags.Intersection && !forEach((<IntersectionType>type).types, t => !isValidBaseType(t));
}
@ -5077,9 +5081,7 @@ namespace ts {
(<InterfaceTypeWithDeclaredMembers>type).declaredCallSignatures = getSignaturesOfSymbol(symbol.members.get("__call"));
(<InterfaceTypeWithDeclaredMembers>type).declaredConstructSignatures = getSignaturesOfSymbol(symbol.members.get("__new"));
(<InterfaceTypeWithDeclaredMembers>type).declaredNumberIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.Number);
(<InterfaceTypeWithDeclaredMembers>type).declaredStringIndexInfo = (getBaseConstructorTypeOfClass(type) === anyType) ?
createIndexInfo(anyType, /*isReadonly*/ false) :
getIndexInfoOfSymbol(symbol, IndexKind.String);
(<InterfaceTypeWithDeclaredMembers>type).declaredStringIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.String);
}
return <InterfaceTypeWithDeclaredMembers>type;
}
@ -5132,7 +5134,9 @@ namespace ts {
addInheritedMembers(members, getPropertiesOfType(instantiatedBaseType));
callSignatures = concatenate(callSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Call));
constructSignatures = concatenate(constructSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Construct));
stringIndexInfo = stringIndexInfo || getIndexInfoOfType(instantiatedBaseType, IndexKind.String);
stringIndexInfo = stringIndexInfo || (instantiatedBaseType === anyType ?
createIndexInfo(anyType, /*isReadonly*/ false) :
getIndexInfoOfType(instantiatedBaseType, IndexKind.String));
numberIndexInfo = numberIndexInfo || getIndexInfoOfType(instantiatedBaseType, IndexKind.Number);
}
}