Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit dc6c33d

Browse files
committed
TS: Fix infinite type expansion issue
1 parent 69a048d commit dc6c33d

5 files changed

Lines changed: 40 additions & 1 deletion

File tree

javascript/extractor/lib/typescript/src/type_table.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,28 @@ function isTypeVariable(type: ts.Type): type is ts.TypeVariable {
2323
return (type.flags & ts.TypeFlags.TypeVariable) !== 0;
2424
}
2525

26+
/**
27+
* Returns `true` if the properties of the given type can safely be extracted
28+
* without restricting expansion depth.
29+
*
30+
* This predicate is very approximate, and considers all unions, intersections,
31+
* named types, and mapped types as potentially unsafe.
32+
*/
33+
function isTypeAlwaysSafeToExpand(type: ts.Type): boolean {
34+
let flags = type.flags;
35+
if (flags & ts.TypeFlags.UnionOrIntersection) {
36+
return false;
37+
}
38+
if (flags & ts.TypeFlags.Object) {
39+
let objectType = type as ts.ObjectType;
40+
let objectFlags = objectType.objectFlags;
41+
if (objectFlags & (ts.ObjectFlags.Reference | ts.ObjectFlags.Mapped)) {
42+
return false;
43+
}
44+
}
45+
return true;
46+
}
47+
2648
/**
2749
* If `type` is a `this` type, returns the enclosing type.
2850
* Otherwise returns `null`.
@@ -784,7 +806,7 @@ export class TypeTable {
784806
while (worklist.length > 0) {
785807
let [type, id] = worklist.pop();
786808
let isShallowContext = typeExtractionState[id] === TypeExtractionState.PendingShallow;
787-
if (isShallowContext && isTypeReference(type)) {
809+
if (isShallowContext && !isTypeAlwaysSafeToExpand(type)) {
788810
typeExtractionState[id] = TypeExtractionState.DoneShallow;
789811
} else {
790812
typeExtractionState[id] = TypeExtractionState.DoneFull;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
interface X {
2+
a: RecursiveMappedType<this> & X;
3+
b: boolean;
4+
}
5+
6+
type RecursiveMappedType<V> = {
7+
[P in keyof V]?: X & RecursiveMappedType<V[P]>
8+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
| recursiveMappedType.ts:2:5:2:5 | a | RecursiveMappedType<this> & X |
2+
| recursiveMappedType.ts:3:5:3:5 | b | boolean |
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import javascript
2+
3+
from Expr e
4+
select e, e.getType()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"include": ["."]
3+
}

0 commit comments

Comments
 (0)