@@ -2623,11 +2623,16 @@ module ts {
2623
2623
return signatures;
2624
2624
}
2625
2625
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.
2626
2631
function getBaseConstructorTypeOfClass(type: InterfaceType): ObjectType {
2627
- if (!type.baseConstructorType ) {
2632
+ if (!type.resolvedBaseConstructorType ) {
2628
2633
let baseTypeNode = getBaseTypeNodeOfClass(type);
2629
2634
if (!baseTypeNode) {
2630
- return type.baseConstructorType = undefinedType;
2635
+ return type.resolvedBaseConstructorType = undefinedType;
2631
2636
}
2632
2637
if (!pushTypeResolution(type)) {
2633
2638
return unknownType;
@@ -2639,45 +2644,50 @@ module ts {
2639
2644
}
2640
2645
if (!popTypeResolution()) {
2641
2646
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;
2643
2648
}
2644
2649
if (baseConstructorType !== unknownType && baseConstructorType !== nullType && !isConstructorType(baseConstructorType)) {
2645
2650
error(baseTypeNode.expression, Diagnostics.Base_expression_is_not_of_a_constructor_function_type);
2646
- return type.baseConstructorType = unknownType;
2651
+ return type.resolvedBaseConstructorType = unknownType;
2647
2652
}
2648
- type.baseConstructorType = baseConstructorType;
2653
+ type.resolvedBaseConstructorType = baseConstructorType;
2649
2654
}
2650
- return type.baseConstructorType ;
2655
+ return type.resolvedBaseConstructorType ;
2651
2656
}
2652
2657
2653
2658
function getBaseTypes(type: InterfaceType): ObjectType[] {
2654
- let typeWithBaseTypes = <InterfaceTypeWithBaseTypes>type;
2655
- if (!typeWithBaseTypes.baseTypes) {
2659
+ if (!type.resolvedBaseTypes) {
2656
2660
if (type.symbol.flags & SymbolFlags.Class) {
2657
- resolveBaseTypesOfClass(typeWithBaseTypes );
2661
+ resolveBaseTypesOfClass(type );
2658
2662
}
2659
2663
else if (type.symbol.flags & SymbolFlags.Interface) {
2660
- resolveBaseTypesOfInterface(typeWithBaseTypes );
2664
+ resolveBaseTypesOfInterface(type );
2661
2665
}
2662
2666
else {
2663
2667
Debug.fail("type must be class or interface");
2664
2668
}
2665
2669
}
2666
- return typeWithBaseTypes.baseTypes ;
2670
+ return type.resolvedBaseTypes ;
2667
2671
}
2668
2672
2669
- function resolveBaseTypesOfClass(type: InterfaceTypeWithBaseTypes ): void {
2670
- type.baseTypes = emptyArray;
2673
+ function resolveBaseTypesOfClass(type: InterfaceType ): void {
2674
+ type.resolvedBaseTypes = emptyArray;
2671
2675
let baseContructorType = getBaseConstructorTypeOfClass(type);
2672
2676
if (!(baseContructorType.flags & TypeFlags.ObjectType)) {
2673
2677
return;
2674
2678
}
2675
2679
let baseTypeNode = getBaseTypeNodeOfClass(type);
2676
2680
let baseType: Type;
2677
2681
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.
2678
2685
baseType = getTypeFromClassOrInterfaceReference(baseTypeNode, baseContructorType.symbol);
2679
2686
}
2680
2687
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.
2681
2691
let constructors = getInstantiatedConstructorsForTypeArguments(baseContructorType, baseTypeNode.typeArguments);
2682
2692
if (!constructors.length) {
2683
2693
error(baseTypeNode.expression, Diagnostics.No_base_constructor_has_the_specified_number_of_type_arguments);
@@ -2697,19 +2707,19 @@ module ts {
2697
2707
typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType));
2698
2708
return;
2699
2709
}
2700
- type.baseTypes = [baseType];
2710
+ type.resolvedBaseTypes = [baseType];
2701
2711
}
2702
2712
2703
- function resolveBaseTypesOfInterface(type: InterfaceTypeWithBaseTypes ): void {
2704
- type.baseTypes = [];
2713
+ function resolveBaseTypesOfInterface(type: InterfaceType ): void {
2714
+ type.resolvedBaseTypes = [];
2705
2715
for (let declaration of type.symbol.declarations) {
2706
2716
if (declaration.kind === SyntaxKind.InterfaceDeclaration && getInterfaceBaseTypeNodes(<InterfaceDeclaration>declaration)) {
2707
2717
for (let node of getInterfaceBaseTypeNodes(<InterfaceDeclaration>declaration)) {
2708
2718
let baseType = getTypeFromTypeNode(node);
2709
2719
if (baseType !== unknownType) {
2710
2720
if (getTargetType(baseType).flags & (TypeFlags.Class | TypeFlags.Interface)) {
2711
2721
if (type !== baseType && !hasBaseType(<InterfaceType>baseType, type)) {
2712
- type.baseTypes .push(baseType);
2722
+ type.resolvedBaseTypes .push(baseType);
2713
2723
}
2714
2724
else {
2715
2725
error(declaration, Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType));
@@ -7421,6 +7431,8 @@ module ts {
7421
7431
if (node.expression.kind === SyntaxKind.SuperKeyword) {
7422
7432
let superType = checkSuperExpression(node.expression);
7423
7433
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.
7424
7436
let baseTypeNode = getClassExtendsHeritageClauseElement(<ClassDeclaration>getAncestor(node, SyntaxKind.ClassDeclaration));
7425
7437
let baseConstructors = getInstantiatedConstructorsForTypeArguments(superType, baseTypeNode.typeArguments);
7426
7438
return resolveCall(node, baseConstructors, candidatesOutArray);
0 commit comments