@@ -4714,7 +4714,7 @@ namespace ts {
47144714 // 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
47154715 // class and all return the instance type of the class. There is no need for further checks and we can apply the
47164716 // type arguments in the same manner as a type reference to get the same error reporting experience.
4717- baseType = getTypeFromClassOrInterfaceReference(baseTypeNode, baseConstructorType.symbol);
4717+ baseType = getTypeFromClassOrInterfaceReference(baseTypeNode, baseConstructorType.symbol, typeArgumentsFromTypeReferenceNode(baseTypeNode) );
47184718 }
47194719 else if (baseConstructorType.flags & TypeFlags.Any) {
47204720 baseType = baseConstructorType;
@@ -5238,7 +5238,7 @@ namespace ts {
52385238 }
52395239 const baseTypeNode = getBaseTypeNodeOfClass(classType);
52405240 const isJavaScript = isInJavaScriptFile(baseTypeNode);
5241- const typeArguments = map (baseTypeNode.typeArguments, getTypeFromTypeNode );
5241+ const typeArguments = typeArgumentsFromTypeReferenceNode (baseTypeNode);
52425242 const typeArgCount = length(typeArguments);
52435243 const result: Signature[] = [];
52445244 for (const baseSig of baseSignatures) {
@@ -6501,7 +6501,7 @@ namespace ts {
65016501 }
65026502
65036503 // Get type from reference to class or interface
6504- function getTypeFromClassOrInterfaceReference(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference, symbol: Symbol): Type {
6504+ function getTypeFromClassOrInterfaceReference(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference, symbol: Symbol, typeArgs: Type[] ): Type {
65056505 const type = <InterfaceType>getDeclaredTypeOfSymbol(getMergedSymbol(symbol));
65066506 const typeParameters = type.localTypeParameters;
65076507 if (typeParameters) {
@@ -6520,7 +6520,7 @@ namespace ts {
65206520 // In a type reference, the outer type parameters of the referenced class or interface are automatically
65216521 // supplied as type arguments and the type reference only specifies arguments for the local type parameters
65226522 // of the class or interface.
6523- const typeArguments = concatenate(type.outerTypeParameters, fillMissingTypeArguments(map(node.typeArguments, getTypeFromTypeNode) , typeParameters, minTypeArgumentCount, node));
6523+ const typeArguments = concatenate(type.outerTypeParameters, fillMissingTypeArguments(typeArgs , typeParameters, minTypeArgumentCount, node));
65246524 return createTypeReference(<GenericType>type, typeArguments);
65256525 }
65266526 if (node.typeArguments) {
@@ -6545,7 +6545,7 @@ namespace ts {
65456545 // Get type from reference to type alias. When a type alias is generic, the declared type of the type alias may include
65466546 // references to the type parameters of the alias. We replace those with the actual type arguments by instantiating the
65476547 // declared type. Instantiations are cached using the type identities of the type arguments as the key.
6548- function getTypeFromTypeAliasReference(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference, symbol: Symbol): Type {
6548+ function getTypeFromTypeAliasReference(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference, symbol: Symbol, typeArguments: Type[] ): Type {
65496549 const type = getDeclaredTypeOfSymbol(symbol);
65506550 const typeParameters = getSymbolLinks(symbol).typeParameters;
65516551 if (typeParameters) {
@@ -6561,7 +6561,6 @@ namespace ts {
65616561 typeParameters.length);
65626562 return unknownType;
65636563 }
6564- const typeArguments = map(node.typeArguments, getTypeFromTypeNode);
65656564 return getTypeAliasInstantiation(symbol, typeArguments);
65666565 }
65676566 if (node.typeArguments) {
@@ -6609,16 +6608,18 @@ namespace ts {
66096608 }
66106609
66116610 function getTypeReferenceType(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference, symbol: Symbol) {
6611+ const typeArguments = typeArgumentsFromTypeReferenceNode(node); // Do unconditionally so we mark type arguments as referenced.
6612+
66126613 if (symbol === unknownSymbol) {
66136614 return unknownType;
66146615 }
66156616
66166617 if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
6617- return getTypeFromClassOrInterfaceReference(node, symbol);
6618+ return getTypeFromClassOrInterfaceReference(node, symbol, typeArguments );
66186619 }
66196620
66206621 if (symbol.flags & SymbolFlags.TypeAlias) {
6621- return getTypeFromTypeAliasReference(node, symbol);
6622+ return getTypeFromTypeAliasReference(node, symbol, typeArguments );
66226623 }
66236624
66246625 if (symbol.flags & SymbolFlags.Value && node.kind === SyntaxKind.JSDocTypeReference) {
@@ -6686,10 +6687,7 @@ namespace ts {
66866687 ? <EntityNameExpression>(<ExpressionWithTypeArguments>node).expression
66876688 : undefined;
66886689 symbol = typeNameOrExpression && resolveEntityName(typeNameOrExpression, SymbolFlags.Type) || unknownSymbol;
6689- type = symbol === unknownSymbol ? unknownType :
6690- symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface) ? getTypeFromClassOrInterfaceReference(node, symbol) :
6691- symbol.flags & SymbolFlags.TypeAlias ? getTypeFromTypeAliasReference(node, symbol) :
6692- getTypeFromNonGenericTypeReference(node, symbol);
6690+ type = getTypeReferenceType(node, symbol);
66936691 }
66946692 // Cache both the resolved symbol and the resolved type. The resolved symbol is needed in when we check the
66956693 // type reference in checkTypeReferenceOrExpressionWithTypeArguments.
@@ -6699,6 +6697,10 @@ namespace ts {
66996697 return links.resolvedType;
67006698 }
67016699
6700+ function typeArgumentsFromTypeReferenceNode(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference): Type[] {
6701+ return map(node.typeArguments, getTypeFromTypeNode);
6702+ }
6703+
67026704 function getTypeFromTypeQueryNode(node: TypeQueryNode): Type {
67036705 const links = getNodeLinks(node);
67046706 if (!links.resolvedType) {
@@ -14318,7 +14320,18 @@ namespace ts {
1431814320 return true;
1431914321 }
1432014322
14323+ function callLikeExpressionMayHaveTypeArguments(node: CallLikeExpression): node is CallExpression | NewExpression {
14324+ // TODO: Also include tagged templates (https://github.com/Microsoft/TypeScript/issues/11947)
14325+ return isCallOrNewExpression(node);
14326+ }
14327+
1432114328 function resolveUntypedCall(node: CallLikeExpression): Signature {
14329+ if (callLikeExpressionMayHaveTypeArguments(node)) {
14330+ // Check type arguments even though we will give an error that untyped calls may not accept type arguments.
14331+ // This gets us diagnostics for the type arguments and marks them as referenced.
14332+ forEach(node.typeArguments, checkSourceElement);
14333+ }
14334+
1432214335 if (node.kind === SyntaxKind.TaggedTemplateExpression) {
1432314336 checkExpression((<TaggedTemplateExpression>node).template);
1432414337 }
0 commit comments