@@ -2623,11 +2623,16 @@ module ts {
26232623 return signatures;
26242624 }
26252625
2626+ // The base constructor of a class can resolve to
2627+ // undefinedType if the class has no extends clause,
2628+ // unknownType if an error occurred during resolution of the extends expression,
2629+ // nullType if the extends expression is the null value, or
2630+ // an object type with at least one construct signature.
26262631 function getBaseConstructorTypeOfClass(type: InterfaceType): ObjectType {
2627- if (!type.baseConstructorType ) {
2632+ if (!type.resolvedBaseConstructorType ) {
26282633 let baseTypeNode = getBaseTypeNodeOfClass(type);
26292634 if (!baseTypeNode) {
2630- return type.baseConstructorType = undefinedType;
2635+ return type.resolvedBaseConstructorType = undefinedType;
26312636 }
26322637 if (!pushTypeResolution(type)) {
26332638 return unknownType;
@@ -2639,45 +2644,50 @@ module ts {
26392644 }
26402645 if (!popTypeResolution()) {
26412646 error(type.symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, symbolToString(type.symbol));
2642- return type.baseConstructorType = unknownType;
2647+ return type.resolvedBaseConstructorType = unknownType;
26432648 }
26442649 if (baseConstructorType !== unknownType && baseConstructorType !== nullType && !isConstructorType(baseConstructorType)) {
26452650 error(baseTypeNode.expression, Diagnostics.Base_expression_is_not_of_a_constructor_function_type);
2646- return type.baseConstructorType = unknownType;
2651+ return type.resolvedBaseConstructorType = unknownType;
26472652 }
2648- type.baseConstructorType = baseConstructorType;
2653+ type.resolvedBaseConstructorType = baseConstructorType;
26492654 }
2650- return type.baseConstructorType ;
2655+ return type.resolvedBaseConstructorType ;
26512656 }
26522657
26532658 function getBaseTypes(type: InterfaceType): ObjectType[] {
2654- let typeWithBaseTypes = <InterfaceTypeWithBaseTypes>type;
2655- if (!typeWithBaseTypes.baseTypes) {
2659+ if (!type.resolvedBaseTypes) {
26562660 if (type.symbol.flags & SymbolFlags.Class) {
2657- resolveBaseTypesOfClass(typeWithBaseTypes );
2661+ resolveBaseTypesOfClass(type );
26582662 }
26592663 else if (type.symbol.flags & SymbolFlags.Interface) {
2660- resolveBaseTypesOfInterface(typeWithBaseTypes );
2664+ resolveBaseTypesOfInterface(type );
26612665 }
26622666 else {
26632667 Debug.fail("type must be class or interface");
26642668 }
26652669 }
2666- return typeWithBaseTypes.baseTypes ;
2670+ return type.resolvedBaseTypes ;
26672671 }
26682672
2669- function resolveBaseTypesOfClass(type: InterfaceTypeWithBaseTypes ): void {
2670- type.baseTypes = emptyArray;
2673+ function resolveBaseTypesOfClass(type: InterfaceType ): void {
2674+ type.resolvedBaseTypes = emptyArray;
26712675 let baseContructorType = getBaseConstructorTypeOfClass(type);
26722676 if (!(baseContructorType.flags & TypeFlags.ObjectType)) {
26732677 return;
26742678 }
26752679 let baseTypeNode = getBaseTypeNodeOfClass(type);
26762680 let baseType: Type;
26772681 if (baseContructorType.symbol && baseContructorType.symbol.flags & SymbolFlags.Class) {
2682+ // When base constructor type is a class we know that the constructors all have the same type parameters as the
2683+ // class and all return the instance type of the class. There is no need for further checks and we can apply the
2684+ // type arguments in the same manner as a type reference to get the same error reporting experience.
26782685 baseType = getTypeFromClassOrInterfaceReference(baseTypeNode, baseContructorType.symbol);
26792686 }
26802687 else {
2688+ // The class derives from a "class-like" constructor function, check that we have at least one construct signature
2689+ // with a matching number of type parameters and use the return type of the first instantiated signature. Elsewhere
2690+ // we check that all instantiated signatures return the same type.
26812691 let constructors = getInstantiatedConstructorsForTypeArguments(baseContructorType, baseTypeNode.typeArguments);
26822692 if (!constructors.length) {
26832693 error(baseTypeNode.expression, Diagnostics.No_base_constructor_has_the_specified_number_of_type_arguments);
@@ -2697,19 +2707,19 @@ module ts {
26972707 typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType));
26982708 return;
26992709 }
2700- type.baseTypes = [baseType];
2710+ type.resolvedBaseTypes = [baseType];
27012711 }
27022712
2703- function resolveBaseTypesOfInterface(type: InterfaceTypeWithBaseTypes ): void {
2704- type.baseTypes = [];
2713+ function resolveBaseTypesOfInterface(type: InterfaceType ): void {
2714+ type.resolvedBaseTypes = [];
27052715 for (let declaration of type.symbol.declarations) {
27062716 if (declaration.kind === SyntaxKind.InterfaceDeclaration && getInterfaceBaseTypeNodes(<InterfaceDeclaration>declaration)) {
27072717 for (let node of getInterfaceBaseTypeNodes(<InterfaceDeclaration>declaration)) {
27082718 let baseType = getTypeFromTypeNode(node);
27092719 if (baseType !== unknownType) {
27102720 if (getTargetType(baseType).flags & (TypeFlags.Class | TypeFlags.Interface)) {
27112721 if (type !== baseType && !hasBaseType(<InterfaceType>baseType, type)) {
2712- type.baseTypes .push(baseType);
2722+ type.resolvedBaseTypes .push(baseType);
27132723 }
27142724 else {
27152725 error(declaration, Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType));
@@ -7421,6 +7431,8 @@ module ts {
74217431 if (node.expression.kind === SyntaxKind.SuperKeyword) {
74227432 let superType = checkSuperExpression(node.expression);
74237433 if (superType !== unknownType) {
7434+ // In super call, the candidate signatures are the matching arity signatures of the base constructor function instantiated
7435+ // with the type arguments specified in the extends clause.
74247436 let baseTypeNode = getClassExtendsHeritageClauseElement(<ClassDeclaration>getAncestor(node, SyntaxKind.ClassDeclaration));
74257437 let baseConstructors = getInstantiatedConstructorsForTypeArguments(superType, baseTypeNode.typeArguments);
74267438 return resolveCall(node, baseConstructors, candidatesOutArray);
0 commit comments