@@ -6814,57 +6814,56 @@ namespace ts {
68146814 return undefined;
68156815 }
68166816
6817- function resolveTypeReferenceName(node: TypeReferenceType, typeReferenceName: EntityNameExpression | EntityName) {
6817+ function resolveTypeReferenceName(typeReferenceName: EntityNameExpression | EntityName, meaning: SymbolFlags ) {
68186818 if (!typeReferenceName) {
68196819 return unknownSymbol;
68206820 }
68216821
6822- const meaning = node.kind === SyntaxKind.JSDocTypeReference
6823- ? SymbolFlags.Type | SymbolFlags.Value
6824- : SymbolFlags.Type;
6825-
68266822 return resolveEntityName(typeReferenceName, meaning) || unknownSymbol;
68276823 }
68286824
68296825 function getTypeReferenceType(node: TypeReferenceType, symbol: Symbol) {
68306826 const typeArguments = typeArgumentsFromTypeReferenceNode(node); // Do unconditionally so we mark type arguments as referenced.
6831- let secondPass = false;
6832- let fallbackType: Type = unknownType;
6833- while (true) {
6834- if (symbol === unknownSymbol) {
6835- return fallbackType;
6836- }
6827+ if (symbol === unknownSymbol) {
6828+ return unknownType;
6829+ }
68376830
6838- if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
6839- return getTypeFromClassOrInterfaceReference(node, symbol, typeArguments);
6840- }
6831+ const type = getTypeReferenceTypeWorker(node, symbol, typeArguments);
6832+ if (type) {
6833+ return type;
6834+ }
68416835
6842- if (symbol.flags & SymbolFlags.TypeAlias) {
6843- return getTypeFromTypeAliasReference(node, symbol, typeArguments);
6836+ if (symbol.flags & SymbolFlags.Value && node.kind === SyntaxKind.JSDocTypeReference) {
6837+ // A JSDocTypeReference may have resolved to a value (as opposed to a type). If
6838+ // the symbol is a constructor function, return the inferred class type; otherwise,
6839+ // the type of this reference is just the type of the value we resolved to.
6840+ const valueType = getTypeOfSymbol(symbol);
6841+ if (valueType.symbol && !isInferredClassType(valueType)) {
6842+ const referenceType = getTypeReferenceTypeWorker(node, valueType.symbol, typeArguments);
6843+ if (referenceType) {
6844+ return referenceType;
6845+ }
68446846 }
68456847
6846- if (symbol.flags & SymbolFlags.Value && node.kind === SyntaxKind.JSDocTypeReference) {
6847- // A JSDocTypeReference may have resolved to a value (as opposed to a type). If
6848- // the symbol is a constructor function, return the inferred class type; otherwise,
6849- // the type of this reference is just the type of the value we resolved to.
6850- if (symbol.flags & SymbolFlags.Function && (symbol.members || getJSDocClassTag(symbol.valueDeclaration))) {
6851- return getInferredClassType(symbol);
6852- }
6848+ // Resolve the type reference as a Type for the purpose of reporting errors.
6849+ resolveTypeReferenceName(getTypeReferenceName(node), SymbolFlags.Type);
6850+ return valueType;
6851+ }
68536852
6854- // Stop if this is the second pass
6855- if (secondPass) {
6856- return fallbackType;
6857- }
6853+ return getTypeFromNonGenericTypeReference(node, symbol);
6854+ }
68586855
6859- // Try to use the symbol of the type (if present) to get a better type on the
6860- // second pass.
6861- fallbackType = getTypeOfSymbol(symbol);
6862- symbol = fallbackType.symbol || unknownSymbol;
6863- secondPass = true;
6864- continue;
6865- }
6856+ function getTypeReferenceTypeWorker(node: TypeReferenceType, symbol: Symbol, typeArguments: Type[]): Type | undefined {
6857+ if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
6858+ return getTypeFromClassOrInterfaceReference(node, symbol, typeArguments);
6859+ }
6860+
6861+ if (symbol.flags & SymbolFlags.TypeAlias) {
6862+ return getTypeFromTypeAliasReference(node, symbol, typeArguments);
6863+ }
68666864
6867- return getTypeFromNonGenericTypeReference(node, symbol);
6865+ if (symbol.flags & SymbolFlags.Function && node.kind === SyntaxKind.JSDocTypeReference && (symbol.members || getJSDocClassTag(symbol.valueDeclaration))) {
6866+ return getInferredClassType(symbol);
68686867 }
68696868 }
68706869
@@ -6908,11 +6907,13 @@ namespace ts {
69086907 if (!links.resolvedType) {
69096908 let symbol: Symbol;
69106909 let type: Type;
6910+ let meaning = SymbolFlags.Type;
69116911 if (node.kind === SyntaxKind.JSDocTypeReference) {
69126912 type = getPrimitiveTypeFromJSDocTypeReference(node);
6913+ meaning |= SymbolFlags.Value;
69136914 }
69146915 if (!type) {
6915- symbol = resolveTypeReferenceName(node, getTypeReferenceName(node));
6916+ symbol = resolveTypeReferenceName(getTypeReferenceName(node), meaning );
69166917 type = getTypeReferenceType(node, symbol);
69176918 }
69186919 // Cache both the resolved symbol and the resolved type. The resolved symbol is needed in when we check the
@@ -16155,6 +16156,12 @@ namespace ts {
1615516156 return links.inferredClassType;
1615616157 }
1615716158
16159+ function isInferredClassType(type: Type) {
16160+ return type.symbol
16161+ && getObjectFlags(type) & ObjectFlags.Anonymous
16162+ && getSymbolLinks(type.symbol).inferredClassType === type;
16163+ }
16164+
1615816165 /**
1615916166 * Syntactically and semantically checks a call or new expression.
1616016167 * @param node The call/new expression to be checked.
0 commit comments