@@ -11090,7 +11090,7 @@ namespace ts {
11090
11090
return errorType;
11091
11091
}
11092
11092
}
11093
- if (node.kind === SyntaxKind.TypeReference && isAliasedType( node)) {
11093
+ if (node.kind === SyntaxKind.TypeReference && isDeferredTypeReferenceNode(<TypeReferenceNode> node)) {
11094
11094
return createDeferredTypeReference(<GenericType>type, <TypeReferenceNode>node, /*mapper*/ undefined);
11095
11095
}
11096
11096
// In a type reference, the outer type parameters of the referenced class or interface are automatically
@@ -11552,10 +11552,19 @@ namespace ts {
11552
11552
return getTupleTypeOfArity(node.elementTypes.length, minLength, !!restElement, readonly, /*associatedNames*/ undefined);
11553
11553
}
11554
11554
11555
+ // Return true if the given type reference node is directly aliased or if it needs to be deferred
11556
+ // because it is possibly contained in a circular chain of eagerly resolved types.
11557
+ function isDeferredTypeReferenceNode(node: TypeReferenceNode | ArrayTypeNode | TupleTypeNode) {
11558
+ return !!getAliasSymbolForTypeNode(node) || isResolvedByTypeAlias(node) &&
11559
+ node.kind === SyntaxKind.ArrayType ?
11560
+ mayResolveTypeAlias((<ArrayTypeNode>node).elementType) :
11561
+ some(node.kind === SyntaxKind.TypeReference ? (<TypeReferenceNode>node).typeArguments : (<TupleTypeNode>node).elementTypes, mayResolveTypeAlias);
11562
+ }
11563
+
11555
11564
// Return true when the given node is transitively contained in type constructs that eagerly
11556
11565
// resolve their constituent types. We include SyntaxKind.TypeReference because type arguments
11557
11566
// of type aliases are eagerly resolved.
11558
- function isAliasedType (node: Node): boolean {
11567
+ function isResolvedByTypeAlias (node: Node): boolean {
11559
11568
const parent = node.parent;
11560
11569
switch (parent.kind) {
11561
11570
case SyntaxKind.ParenthesizedType:
@@ -11565,21 +11574,52 @@ namespace ts {
11565
11574
case SyntaxKind.IndexedAccessType:
11566
11575
case SyntaxKind.ConditionalType:
11567
11576
case SyntaxKind.TypeOperator:
11568
- return isAliasedType (parent);
11577
+ return isResolvedByTypeAlias (parent);
11569
11578
case SyntaxKind.TypeAliasDeclaration:
11570
11579
return true;
11571
11580
}
11572
11581
return false;
11573
11582
}
11574
11583
11584
+ // Return true if resolving the given node (i.e. getTypeFromTypeNode) possibly causes resolution
11585
+ // of a type alias.
11586
+ function mayResolveTypeAlias(node: Node): boolean {
11587
+ switch (node.kind) {
11588
+ case SyntaxKind.TypeReference:
11589
+ return isJSDocTypeReference(node) || !!(resolveTypeReferenceName((<TypeReferenceNode>node).typeName, SymbolFlags.Type).flags & SymbolFlags.TypeAlias);
11590
+ case SyntaxKind.TypeQuery:
11591
+ return true;
11592
+ case SyntaxKind.TypeOperator:
11593
+ if ((<TypeOperatorNode>node).operator === SyntaxKind.UniqueKeyword) break;
11594
+ case SyntaxKind.ParenthesizedType:
11595
+ case SyntaxKind.OptionalType:
11596
+ case SyntaxKind.JSDocOptionalType:
11597
+ case SyntaxKind.JSDocNullableType:
11598
+ case SyntaxKind.JSDocNonNullableType:
11599
+ case SyntaxKind.JSDocTypeExpression:
11600
+ return mayResolveTypeAlias((<TypeOperatorNode | ParenthesizedTypeNode | OptionalTypeNode | JSDocTypeReferencingNode>node).type);
11601
+ case SyntaxKind.RestType:
11602
+ return (<RestTypeNode>node).type.kind !== SyntaxKind.ArrayType || mayResolveTypeAlias((<ArrayTypeNode>(<RestTypeNode>node).type).elementType);
11603
+ case SyntaxKind.UnionType:
11604
+ case SyntaxKind.IntersectionType:
11605
+ return some((<UnionOrIntersectionTypeNode>node).types, mayResolveTypeAlias);
11606
+ case SyntaxKind.IndexedAccessType:
11607
+ return mayResolveTypeAlias((<IndexedAccessTypeNode>node).objectType) || mayResolveTypeAlias((<IndexedAccessTypeNode>node).indexType);
11608
+ case SyntaxKind.ConditionalType:
11609
+ return mayResolveTypeAlias((<ConditionalTypeNode>node).checkType) || mayResolveTypeAlias((<ConditionalTypeNode>node).extendsType) ||
11610
+ mayResolveTypeAlias((<ConditionalTypeNode>node).trueType) || mayResolveTypeAlias((<ConditionalTypeNode>node).falseType);
11611
+ }
11612
+ return false;
11613
+ }
11614
+
11575
11615
function getTypeFromArrayOrTupleTypeNode(node: ArrayTypeNode | TupleTypeNode): Type {
11576
11616
const links = getNodeLinks(node);
11577
11617
if (!links.resolvedType) {
11578
11618
const target = getArrayOrTupleTargetType(node);
11579
11619
if (target === emptyGenericType) {
11580
11620
links.resolvedType = emptyObjectType;
11581
11621
}
11582
- else if (isAliasedType (node)) {
11622
+ else if (isDeferredTypeReferenceNode (node)) {
11583
11623
links.resolvedType = node.kind === SyntaxKind.TupleType && node.elementTypes.length === 0 ? target :
11584
11624
createDeferredTypeReference(target, node, /*mapper*/ undefined);
11585
11625
}
@@ -12902,7 +12942,7 @@ namespace ts {
12902
12942
return links.resolvedType;
12903
12943
}
12904
12944
12905
- function getAliasSymbolForTypeNode(node: TypeNode ) {
12945
+ function getAliasSymbolForTypeNode(node: Node ) {
12906
12946
let host = node.parent;
12907
12947
while (isParenthesizedTypeNode(host) || isTypeOperatorNode(host) && host.operator === SyntaxKind.ReadonlyKeyword) {
12908
12948
host = host.parent;
0 commit comments