@@ -19555,30 +19555,33 @@ namespace ts {
19555
19555
function isDeeplyNestedType(type: Type, stack: Type[], depth: number): boolean {
19556
19556
if (depth >= 5) {
19557
19557
const identity = getRecursionIdentity(type);
19558
- if (identity) {
19559
- let count = 0;
19560
- for (let i = 0; i < depth; i++) {
19561
- if (getRecursionIdentity(stack[i]) === identity) {
19562
- count++;
19563
- if (count >= 5) {
19564
- return true;
19565
- }
19558
+ let count = 0;
19559
+ for (let i = 0; i < depth; i++) {
19560
+ if (getRecursionIdentity(stack[i]) === identity) {
19561
+ count++;
19562
+ if (count >= 5) {
19563
+ return true;
19566
19564
}
19567
19565
}
19568
19566
}
19569
19567
}
19570
19568
return false;
19571
19569
}
19572
19570
19573
- // Types with constituents that could circularly reference the type have a recursion identity. The recursion
19574
- // identity is some object that is common to instantiations of the type with the same origin.
19575
- function getRecursionIdentity(type: Type): object | undefined {
19571
+ // The recursion identity of a type is an object identity that is shared among multiple instantiations of the type.
19572
+ // We track recursion identities in order to identify deeply nested and possibly infinite type instantiations with
19573
+ // the same origin. For example, when type parameters are in scope in an object type such as { x: T }, all
19574
+ // instantiations of that type have the same recursion identity. The default recursion identity is the object
19575
+ // identity of the type, meaning that every type is unique. Generally, types with constituents that could circularly
19576
+ // reference the type have a recursion identity that differs from the object identity.
19577
+ function getRecursionIdentity(type: Type): object {
19578
+ // Object and array literals are known not to contain recursive references and don't need a recursion identity.
19576
19579
if (type.flags & TypeFlags.Object && !isObjectOrArrayLiteralType(type)) {
19577
19580
if (getObjectFlags(type) && ObjectFlags.Reference && (type as TypeReference).node) {
19578
19581
// Deferred type references are tracked through their associated AST node. This gives us finer
19579
19582
// granularity than using their associated target because each manifest type reference has a
19580
19583
// unique AST node.
19581
- return (type as TypeReference).node;
19584
+ return (type as TypeReference).node! ;
19582
19585
}
19583
19586
if (type.symbol && !(getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol.flags & SymbolFlags.Class)) {
19584
19587
// We track all object types that have an associated symbol (representing the origin of the type), but
@@ -19590,18 +19593,19 @@ namespace ts {
19590
19593
return type.target;
19591
19594
}
19592
19595
}
19596
+ if (type.flags & TypeFlags.TypeParameter) {
19597
+ return type.symbol;
19598
+ }
19593
19599
if (type.flags & TypeFlags.IndexedAccess) {
19594
19600
// Identity is the leftmost object type in a chain of indexed accesses, eg, in A[P][Q] it is A
19595
- do {
19596
- type = (type as IndexedAccessType).objectType;
19597
- } while (type.flags & TypeFlags.IndexedAccess);
19601
+ do { type = (type as IndexedAccessType).objectType } while (type.flags & TypeFlags.IndexedAccess);
19598
19602
return type;
19599
19603
}
19600
19604
if (type.flags & TypeFlags.Conditional) {
19601
19605
// The root object represents the origin of the conditional type
19602
19606
return (type as ConditionalType).root;
19603
19607
}
19604
- return undefined ;
19608
+ return type ;
19605
19609
}
19606
19610
19607
19611
function isPropertyIdenticalTo(sourceProp: Symbol, targetProp: Symbol): boolean {
@@ -19785,13 +19789,7 @@ namespace ts {
19785
19789
function isArrayLikeType(type: Type): boolean {
19786
19790
// A type is array-like if it is a reference to the global Array or global ReadonlyArray type,
19787
19791
// or if it is not the undefined or null type and if it is assignable to ReadonlyArray<any>
19788
- return isArrayType(type) || hasArrayOrReadonlyArrayBaseType(type) || !(type.flags & TypeFlags.Nullable) && isTypeAssignableTo(type, anyReadonlyArrayType);
19789
- }
19790
-
19791
- function hasArrayOrReadonlyArrayBaseType(type: Type): boolean {
19792
- return !!(getObjectFlags(type) & ObjectFlags.Reference)
19793
- && !!(getObjectFlags((type as TypeReference).target) & ObjectFlags.ClassOrInterface)
19794
- && some(getBaseTypes((type as TypeReference).target as InterfaceType), isArrayType);
19792
+ return isArrayType(type) || !(type.flags & TypeFlags.Nullable) && isTypeAssignableTo(type, anyReadonlyArrayType);
19795
19793
}
19796
19794
19797
19795
function isEmptyArrayLiteralType(type: Type): boolean {
@@ -21024,16 +21022,16 @@ namespace ts {
21024
21022
// We stop inferring and report a circularity if we encounter duplicate recursion identities on both
21025
21023
// the source side and the target side.
21026
21024
const saveExpandingFlags = expandingFlags;
21027
- const sourceIdentity = getRecursionIdentity(source) || source ;
21028
- const targetIdentity = getRecursionIdentity(target) || target ;
21029
- if (sourceIdentity && contains(sourceStack, sourceIdentity)) expandingFlags |= ExpandingFlags.Source;
21030
- if (targetIdentity && contains(targetStack, targetIdentity)) expandingFlags |= ExpandingFlags.Target;
21025
+ const sourceIdentity = getRecursionIdentity(source);
21026
+ const targetIdentity = getRecursionIdentity(target);
21027
+ if (contains(sourceStack, sourceIdentity)) expandingFlags |= ExpandingFlags.Source;
21028
+ if (contains(targetStack, targetIdentity)) expandingFlags |= ExpandingFlags.Target;
21031
21029
if (expandingFlags !== ExpandingFlags.Both) {
21032
- if (sourceIdentity) (sourceStack || (sourceStack = [])).push(sourceIdentity);
21033
- if (targetIdentity) (targetStack || (targetStack = [])).push(targetIdentity);
21030
+ (sourceStack || (sourceStack = [])).push(sourceIdentity);
21031
+ (targetStack || (targetStack = [])).push(targetIdentity);
21034
21032
action(source, target);
21035
- if (targetIdentity) targetStack.pop();
21036
- if (sourceIdentity) sourceStack.pop();
21033
+ targetStack.pop();
21034
+ sourceStack.pop();
21037
21035
}
21038
21036
else {
21039
21037
inferencePriority = InferencePriority.Circularity;
0 commit comments