From 765ac7ccd1e1999715cc1f753d87564372bb6f7d Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 29 Mar 2017 16:09:33 -0700 Subject: [PATCH] Improve handling of any as a base type Also improve how the string indexer for any-inheriting types is added. --- src/compiler/checker.ts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 128e5c86bdc..717553e4848 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -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((type).types, t => !isValidBaseType(t)); } @@ -5077,9 +5081,7 @@ namespace ts { (type).declaredCallSignatures = getSignaturesOfSymbol(symbol.members.get("__call")); (type).declaredConstructSignatures = getSignaturesOfSymbol(symbol.members.get("__new")); (type).declaredNumberIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.Number); - (type).declaredStringIndexInfo = (getBaseConstructorTypeOfClass(type) === anyType) ? - createIndexInfo(anyType, /*isReadonly*/ false) : - getIndexInfoOfSymbol(symbol, IndexKind.String); + (type).declaredStringIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.String); } return 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); } }