mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
apply captured type parameters to returned classes
Get instantiated constructors for classes with captured (outer) type parameters that have not yet been applied. The fast path was incorrect for these classes.
This commit is contained in:
+23
-6
@@ -2868,23 +2868,25 @@ namespace ts {
|
||||
|
||||
function resolveBaseTypesOfClass(type: InterfaceType): void {
|
||||
type.resolvedBaseTypes = type.resolvedBaseTypes || emptyArray;
|
||||
let baseContructorType = getBaseConstructorTypeOfClass(type);
|
||||
if (!(baseContructorType.flags & TypeFlags.ObjectType)) {
|
||||
let baseConstructorType = getBaseConstructorTypeOfClass(type);
|
||||
if (!(baseConstructorType.flags & TypeFlags.ObjectType)) {
|
||||
return;
|
||||
}
|
||||
let baseTypeNode = getBaseTypeNodeOfClass(type);
|
||||
let baseType: Type;
|
||||
if (baseContructorType.symbol && baseContructorType.symbol.flags & SymbolFlags.Class) {
|
||||
// When base constructor type is a class we know that the constructors all have the same type parameters as the
|
||||
let originalBaseType = baseConstructorType && baseConstructorType.symbol ? getDeclaredTypeOfSymbol(baseConstructorType.symbol) : undefined;
|
||||
if (baseConstructorType.symbol && baseConstructorType.symbol.flags & SymbolFlags.Class &&
|
||||
!baseTypeHasUnappliedOuterTypeParameters(originalBaseType)) {
|
||||
// When base constructor type is a class with no captured type arguments we know that the constructors all have the same type parameters as the
|
||||
// class and all return the instance type of the class. There is no need for further checks and we can apply the
|
||||
// type arguments in the same manner as a type reference to get the same error reporting experience.
|
||||
baseType = getTypeFromClassOrInterfaceReference(baseTypeNode, baseContructorType.symbol);
|
||||
baseType = getTypeFromClassOrInterfaceReference(baseTypeNode, baseConstructorType.symbol);
|
||||
}
|
||||
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
|
||||
// we check that all instantiated signatures return the same type.
|
||||
let constructors = getInstantiatedConstructorsForTypeArguments(baseContructorType, baseTypeNode.typeArguments);
|
||||
let constructors = getInstantiatedConstructorsForTypeArguments(baseConstructorType, baseTypeNode.typeArguments);
|
||||
if (!constructors.length) {
|
||||
error(baseTypeNode.expression, Diagnostics.No_base_constructor_has_the_specified_number_of_type_arguments);
|
||||
return;
|
||||
@@ -2911,6 +2913,21 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function baseTypeHasUnappliedOuterTypeParameters(type: Type): boolean {
|
||||
let originalBaseType = <InterfaceType>type;
|
||||
let originalTypeReference = <TypeReference>type;
|
||||
if (originalBaseType.outerTypeParameters) {
|
||||
// an unapplied type type parameter is one
|
||||
// whose argument symbol is still the same as the parameter symbol
|
||||
for (let i = 0; i < originalBaseType.outerTypeParameters.length; i++) {
|
||||
if (originalBaseType.outerTypeParameters[i].symbol === originalTypeReference.typeArguments[i].symbol) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function resolveBaseTypesOfInterface(type: InterfaceType): void {
|
||||
type.resolvedBaseTypes = type.resolvedBaseTypes || emptyArray;
|
||||
for (let declaration of type.symbol.declarations) {
|
||||
|
||||
Reference in New Issue
Block a user