@@ -3732,11 +3732,16 @@ namespace ts {
37323732 return getObjectFlags(type) & ObjectFlags.Reference ? (<TypeReference>type).target : type;
37333733 }
37343734
3735- function hasBaseType(type: InterfaceType , checkBase: InterfaceType ) {
3735+ function hasBaseType(type: BaseType , checkBase: BaseType ) {
37363736 return check(type);
3737- function check(type: InterfaceType): boolean {
3738- const target = <InterfaceType>getTargetType(type);
3739- return target === checkBase || forEach(getBaseTypes(target), check);
3737+ function check(type: BaseType): boolean {
3738+ if (getObjectFlags(type) & (ObjectFlags.ClassOrInterface | ObjectFlags.Reference)) {
3739+ const target = <InterfaceType>getTargetType(type);
3740+ return target === checkBase || forEach(getBaseTypes(target), check);
3741+ }
3742+ else if (type.flags & TypeFlags.Intersection) {
3743+ return forEach((<IntersectionType>type).types, check);
3744+ }
37403745 }
37413746 }
37423747
@@ -3862,7 +3867,7 @@ namespace ts {
38623867 return type.resolvedBaseConstructorType;
38633868 }
38643869
3865- function getBaseTypes(type: InterfaceType): ObjectType [] {
3870+ function getBaseTypes(type: InterfaceType): BaseType [] {
38663871 if (!type.resolvedBaseTypes) {
38673872 if (type.objectFlags & ObjectFlags.Tuple) {
38683873 type.resolvedBaseTypes = [createArrayType(getUnionType(type.typeParameters))];
@@ -3922,11 +3927,11 @@ namespace ts {
39223927 if (baseType === unknownType) {
39233928 return;
39243929 }
3925- if (!(getObjectFlags(getTargetType( baseType)) & ObjectFlags.ClassOrInterface )) {
3930+ if (!isValidBaseType( baseType)) {
39263931 error(baseTypeNode.expression, Diagnostics.Base_constructor_return_type_0_is_not_a_class_or_interface_type, typeToString(baseType));
39273932 return;
39283933 }
3929- if (type === baseType || hasBaseType(<InterfaceType >baseType, type)) {
3934+ if (type === baseType || hasBaseType(<BaseType >baseType, type)) {
39303935 error(valueDecl, Diagnostics.Type_0_recursively_references_itself_as_a_base_type,
39313936 typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType));
39323937 return;
@@ -3951,15 +3956,22 @@ namespace ts {
39513956 return true;
39523957 }
39533958
3959+ // A valid base type is any non-generic object type or intersection of non-generic
3960+ // object types.
3961+ function isValidBaseType(type: Type): boolean {
3962+ return type.flags & TypeFlags.Object && !isGenericMappedType(type) ||
3963+ type.flags & TypeFlags.Intersection && !forEach((<IntersectionType>type).types, t => !isValidBaseType(t));
3964+ }
3965+
39543966 function resolveBaseTypesOfInterface(type: InterfaceType): void {
39553967 type.resolvedBaseTypes = type.resolvedBaseTypes || emptyArray;
39563968 for (const declaration of type.symbol.declarations) {
39573969 if (declaration.kind === SyntaxKind.InterfaceDeclaration && getInterfaceBaseTypeNodes(<InterfaceDeclaration>declaration)) {
39583970 for (const node of getInterfaceBaseTypeNodes(<InterfaceDeclaration>declaration)) {
39593971 const baseType = getTypeFromTypeNode(node);
39603972 if (baseType !== unknownType) {
3961- if (getObjectFlags(getTargetType( baseType)) & ObjectFlags.ClassOrInterface ) {
3962- if (type !== baseType && !hasBaseType(<InterfaceType >baseType, type)) {
3973+ if (isValidBaseType( baseType)) {
3974+ if (type !== baseType && !hasBaseType(<BaseType >baseType, type)) {
39633975 if (type.resolvedBaseTypes === emptyArray) {
39643976 type.resolvedBaseTypes = [<ObjectType>baseType];
39653977 }
@@ -4317,6 +4329,9 @@ namespace ts {
43174329 return createTypeReference((<TypeReference>type).target,
43184330 concatenate((<TypeReference>type).typeArguments, [thisArgument || (<TypeReference>type).target.thisType]));
43194331 }
4332+ if (type.flags & TypeFlags.Intersection) {
4333+ return getIntersectionType(map((<IntersectionType>type).types, t => getTypeWithThisArgument(t, thisArgument)));
4334+ }
43204335 return type;
43214336 }
43224337
@@ -4350,8 +4365,8 @@ namespace ts {
43504365 }
43514366 const thisArgument = lastOrUndefined(typeArguments);
43524367 for (const baseType of baseTypes) {
4353- const instantiatedBaseType = thisArgument ? getTypeWithThisArgument(<ObjectType> instantiateType(baseType, mapper), thisArgument) : baseType;
4354- addInheritedMembers(members, getPropertiesOfObjectType (instantiatedBaseType));
4368+ const instantiatedBaseType = thisArgument ? getTypeWithThisArgument(instantiateType(baseType, mapper), thisArgument) : baseType;
4369+ addInheritedMembers(members, getPropertiesOfType (instantiatedBaseType));
43554370 callSignatures = concatenate(callSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Call));
43564371 constructSignatures = concatenate(constructSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Construct));
43574372 stringIndexInfo = stringIndexInfo || getIndexInfoOfType(instantiatedBaseType, IndexKind.String);
@@ -18216,16 +18231,18 @@ namespace ts {
1821618231 return;
1821718232 }
1821818233
18234+ const propDeclaration = prop.valueDeclaration;
18235+
1821918236 // index is numeric and property name is not valid numeric literal
18220- if (indexKind === IndexKind.Number && !isNumericName(prop.valueDeclaration .name)) {
18237+ if (indexKind === IndexKind.Number && propDeclaration && !isNumericName(propDeclaration .name)) {
1822118238 return;
1822218239 }
1822318240
1822418241 // perform property check if property or indexer is declared in 'type'
1822518242 // this allows to rule out cases when both property and indexer are inherited from the base class
1822618243 let errorNode: Node;
18227- if (prop.valueDeclaration .name.kind === SyntaxKind.ComputedPropertyName || prop.parent === containingType.symbol) {
18228- errorNode = prop.valueDeclaration ;
18244+ if (propDeclaration && propDeclaration .name.kind === SyntaxKind.ComputedPropertyName || prop.parent === containingType.symbol) {
18245+ errorNode = propDeclaration ;
1822918246 }
1823018247 else if (indexDeclaration) {
1823118248 errorNode = indexDeclaration;
@@ -18364,7 +18381,7 @@ namespace ts {
1836418381 checkTypeAssignableTo(staticType, getTypeWithoutSignatures(staticBaseType), node.name || node,
1836518382 Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1);
1836618383
18367- if (baseType.symbol.valueDeclaration &&
18384+ if (baseType.symbol && baseType.symbol .valueDeclaration &&
1836818385 !isInAmbientContext(baseType.symbol.valueDeclaration) &&
1836918386 baseType.symbol.valueDeclaration.kind === SyntaxKind.ClassDeclaration) {
1837018387 if (!isBlockScopedNameDeclaredBeforeUse(baseType.symbol.valueDeclaration, node)) {
@@ -18437,7 +18454,7 @@ namespace ts {
1843718454 return forEach(symbol.declarations, d => isClassLike(d) ? d : undefined);
1843818455 }
1843918456
18440- function checkKindsOfPropertyMemberOverrides(type: InterfaceType, baseType: ObjectType ): void {
18457+ function checkKindsOfPropertyMemberOverrides(type: InterfaceType, baseType: BaseType ): void {
1844118458
1844218459 // TypeScript 1.0 spec (April 2014): 8.2.3
1844318460 // A derived class inherits all members from its base class it doesn't override.
@@ -18454,7 +18471,7 @@ namespace ts {
1845418471 // derived class instance member variables and accessors, but not by other kinds of members.
1845518472
1845618473 // NOTE: assignability is checked in checkClassDeclaration
18457- const baseProperties = getPropertiesOfObjectType (baseType);
18474+ const baseProperties = getPropertiesOfType (baseType);
1845818475 for (const baseProperty of baseProperties) {
1845918476 const base = getTargetSymbol(baseProperty);
1846018477
@@ -18578,7 +18595,7 @@ namespace ts {
1857818595 let ok = true;
1857918596
1858018597 for (const base of baseTypes) {
18581- const properties = getPropertiesOfObjectType (getTypeWithThisArgument(base, type.thisType));
18598+ const properties = getPropertiesOfType (getTypeWithThisArgument(base, type.thisType));
1858218599 for (const prop of properties) {
1858318600 const existing = seen.get(prop.name);
1858418601 if (!existing) {
0 commit comments