Skip to content

Commit 250d5a8

Browse files
authored
Merge pull request #33050 from microsoft/recursiveTypeReferences
Recursive type references
2 parents 4ee251b + 7fd93fd commit 250d5a8

File tree

86 files changed

+2195
-1145
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+2195
-1145
lines changed

src/compiler/checker.ts

+201-133
Large diffs are not rendered by default.

src/compiler/symbolWalker.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ namespace ts {
1010
getResolvedSymbol: (node: Node) => Symbol,
1111
getIndexTypeOfStructuredType: (type: Type, kind: IndexKind) => Type | undefined,
1212
getConstraintOfTypeParameter: (typeParameter: TypeParameter) => Type | undefined,
13-
getFirstIdentifier: (node: EntityNameOrEntityNameExpression) => Identifier) {
13+
getFirstIdentifier: (node: EntityNameOrEntityNameExpression) => Identifier,
14+
getTypeArguments: (type: TypeReference) => readonly Type[]) {
1415

1516
return getSymbolWalker;
1617

@@ -89,7 +90,7 @@ namespace ts {
8990

9091
function visitTypeReference(type: TypeReference): void {
9192
visitType(type.target);
92-
forEach(type.typeArguments, visitType);
93+
forEach(getTypeArguments(type), visitType);
9394
}
9495

9596
function visitTypeParameter(type: TypeParameter): void {

src/compiler/types.ts

+15-1
Original file line numberDiff line numberDiff line change
@@ -3193,6 +3193,7 @@ namespace ts {
31933193
/* @internal */ getParameterType(signature: Signature, parameterIndex: number): Type;
31943194
getNullableType(type: Type, flags: TypeFlags): Type;
31953195
getNonNullableType(type: Type): Type;
3196+
getTypeArguments(type: TypeReference): readonly Type[];
31963197

31973198
// TODO: GH#18217 `xToDeclaration` calls are frequently asserted as defined.
31983199
/** Note that the resulting nodes cannot be checked. */
@@ -4027,6 +4028,8 @@ namespace ts {
40274028
contextFreeType?: Type; // Cached context-free type used by the first pass of inference; used when a function's return is partially contextually sensitive
40284029
deferredNodes?: Map<Node>; // Set of nodes whose checking has been deferred
40294030
capturedBlockScopeBindings?: Symbol[]; // Block-scoped bindings captured beneath this part of an IterationStatement
4031+
outerTypeParameters?: TypeParameter[]; // Outer type parameters of anonymous object type
4032+
instantiations?: Map<Type>; // Instantiations of generic type alias (undefined if non-generic)
40304033
isExhaustive?: boolean; // Is node an exhaustive switch statement
40314034
}
40324035

@@ -4274,11 +4277,22 @@ namespace ts {
42744277
*/
42754278
export interface TypeReference extends ObjectType {
42764279
target: GenericType; // Type reference target
4277-
typeArguments?: readonly Type[]; // Type reference type arguments (undefined if none)
4280+
node?: TypeReferenceNode | ArrayTypeNode | TupleTypeNode;
4281+
/* @internal */
4282+
mapper?: TypeMapper;
4283+
/* @internal */
4284+
resolvedTypeArguments?: readonly Type[]; // Resolved type reference type arguments
42784285
/* @internal */
42794286
literalType?: TypeReference; // Clone of type with ObjectFlags.ArrayLiteral set
42804287
}
42814288

4289+
export interface DeferredTypeReference extends TypeReference {
4290+
/* @internal */
4291+
node: TypeReferenceNode | ArrayTypeNode | TupleTypeNode;
4292+
/* @internal */
4293+
mapper?: TypeMapper;
4294+
}
4295+
42824296
/* @internal */
42834297
export const enum VarianceFlags {
42844298
Invariant = 0, // Neither covariant nor contravariant

src/services/codefixes/inferFromUsage.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -993,8 +993,8 @@ namespace ts.codefix {
993993
}
994994
else if (getObjectFlags(genericType) & ObjectFlags.Reference && getObjectFlags(usageType) & ObjectFlags.Reference) {
995995
// this is wrong because we need a reference to the targetType to, so we can check that it's also a reference
996-
const genericArgs = (genericType as TypeReference).typeArguments;
997-
const usageArgs = (usageType as TypeReference).typeArguments;
996+
const genericArgs = checker.getTypeArguments(genericType as TypeReference);
997+
const usageArgs = checker.getTypeArguments(usageType as TypeReference);
998998
const types = [];
999999
if (genericArgs && usageArgs) {
10001000
for (let i = 0; i < genericArgs.length; i++) {

tests/baselines/reference/api/tsserverlibrary.d.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -1967,6 +1967,7 @@ declare namespace ts {
19671967
getReturnTypeOfSignature(signature: Signature): Type;
19681968
getNullableType(type: Type, flags: TypeFlags): Type;
19691969
getNonNullableType(type: Type): Type;
1970+
getTypeArguments(type: TypeReference): readonly Type[];
19701971
/** Note that the resulting nodes cannot be checked. */
19711972
typeToTypeNode(type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): TypeNode | undefined;
19721973
/** Note that the resulting nodes cannot be checked. */
@@ -2388,7 +2389,9 @@ declare namespace ts {
23882389
*/
23892390
export interface TypeReference extends ObjectType {
23902391
target: GenericType;
2391-
typeArguments?: readonly Type[];
2392+
node?: TypeReferenceNode | ArrayTypeNode | TupleTypeNode;
2393+
}
2394+
export interface DeferredTypeReference extends TypeReference {
23922395
}
23932396
export interface GenericType extends InterfaceType, TypeReference {
23942397
}

tests/baselines/reference/api/typescript.d.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -1967,6 +1967,7 @@ declare namespace ts {
19671967
getReturnTypeOfSignature(signature: Signature): Type;
19681968
getNullableType(type: Type, flags: TypeFlags): Type;
19691969
getNonNullableType(type: Type): Type;
1970+
getTypeArguments(type: TypeReference): readonly Type[];
19701971
/** Note that the resulting nodes cannot be checked. */
19711972
typeToTypeNode(type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): TypeNode | undefined;
19721973
/** Note that the resulting nodes cannot be checked. */
@@ -2388,7 +2389,9 @@ declare namespace ts {
23882389
*/
23892390
export interface TypeReference extends ObjectType {
23902391
target: GenericType;
2391-
typeArguments?: readonly Type[];
2392+
node?: TypeReferenceNode | ArrayTypeNode | TupleTypeNode;
2393+
}
2394+
export interface DeferredTypeReference extends TypeReference {
23922395
}
23932396
export interface GenericType extends InterfaceType, TypeReference {
23942397
}
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
=== tests/cases/conformance/async/es5/asyncAliasReturnType_es5.ts ===
22
type PromiseAlias<T> = Promise<T>;
3-
>PromiseAlias : Promise<T>
3+
>PromiseAlias : PromiseAlias<T>
44

55
async function f(): PromiseAlias<void> {
6-
>f : () => Promise<void>
6+
>f : () => PromiseAlias<void>
77
}
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
=== tests/cases/conformance/async/es6/asyncAliasReturnType_es6.ts ===
22
type PromiseAlias<T> = Promise<T>;
3-
>PromiseAlias : Promise<T>
3+
>PromiseAlias : PromiseAlias<T>
44

55
async function f(): PromiseAlias<void> {
6-
>f : () => Promise<void>
6+
>f : () => PromiseAlias<void>
77
}

tests/baselines/reference/asyncAwait_es2017.types

+16-16
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
=== tests/cases/conformance/async/es2017/asyncAwait_es2017.ts ===
22
type MyPromise<T> = Promise<T>;
3-
>MyPromise : Promise<T>
3+
>MyPromise : MyPromise<T>
44

55
declare var MyPromise: typeof Promise;
66
>MyPromise : PromiseConstructor
@@ -10,7 +10,7 @@ declare var p: Promise<number>;
1010
>p : Promise<number>
1111

1212
declare var mp: MyPromise<number>;
13-
>mp : Promise<number>
13+
>mp : MyPromise<number>
1414

1515
async function f0() { }
1616
>f0 : () => Promise<void>
@@ -19,7 +19,7 @@ async function f1(): Promise<void> { }
1919
>f1 : () => Promise<void>
2020

2121
async function f3(): MyPromise<void> { }
22-
>f3 : () => Promise<void>
22+
>f3 : () => MyPromise<void>
2323

2424
let f4 = async function() { }
2525
>f4 : () => Promise<void>
@@ -30,8 +30,8 @@ let f5 = async function(): Promise<void> { }
3030
>async function(): Promise<void> { } : () => Promise<void>
3131

3232
let f6 = async function(): MyPromise<void> { }
33-
>f6 : () => Promise<void>
34-
>async function(): MyPromise<void> { } : () => Promise<void>
33+
>f6 : () => MyPromise<void>
34+
>async function(): MyPromise<void> { } : () => MyPromise<void>
3535

3636
let f7 = async () => { };
3737
>f7 : () => Promise<void>
@@ -42,8 +42,8 @@ let f8 = async (): Promise<void> => { };
4242
>async (): Promise<void> => { } : () => Promise<void>
4343

4444
let f9 = async (): MyPromise<void> => { };
45-
>f9 : () => Promise<void>
46-
>async (): MyPromise<void> => { } : () => Promise<void>
45+
>f9 : () => MyPromise<void>
46+
>async (): MyPromise<void> => { } : () => MyPromise<void>
4747

4848
let f10 = async () => p;
4949
>f10 : () => Promise<number>
@@ -53,21 +53,21 @@ let f10 = async () => p;
5353
let f11 = async () => mp;
5454
>f11 : () => Promise<number>
5555
>async () => mp : () => Promise<number>
56-
>mp : Promise<number>
56+
>mp : MyPromise<number>
5757

5858
let f12 = async (): Promise<number> => mp;
5959
>f12 : () => Promise<number>
6060
>async (): Promise<number> => mp : () => Promise<number>
61-
>mp : Promise<number>
61+
>mp : MyPromise<number>
6262

6363
let f13 = async (): MyPromise<number> => p;
64-
>f13 : () => Promise<number>
65-
>async (): MyPromise<number> => p : () => Promise<number>
64+
>f13 : () => MyPromise<number>
65+
>async (): MyPromise<number> => p : () => MyPromise<number>
6666
>p : Promise<number>
6767

6868
let o = {
69-
>o : { m1(): Promise<void>; m2(): Promise<void>; m3(): Promise<void>; }
70-
>{ async m1() { }, async m2(): Promise<void> { }, async m3(): MyPromise<void> { }} : { m1(): Promise<void>; m2(): Promise<void>; m3(): Promise<void>; }
69+
>o : { m1(): Promise<void>; m2(): Promise<void>; m3(): MyPromise<void>; }
70+
>{ async m1() { }, async m2(): Promise<void> { }, async m3(): MyPromise<void> { }} : { m1(): Promise<void>; m2(): Promise<void>; m3(): MyPromise<void>; }
7171

7272
async m1() { },
7373
>m1 : () => Promise<void>
@@ -76,7 +76,7 @@ let o = {
7676
>m2 : () => Promise<void>
7777

7878
async m3(): MyPromise<void> { }
79-
>m3 : () => Promise<void>
79+
>m3 : () => MyPromise<void>
8080

8181
};
8282

@@ -90,7 +90,7 @@ class C {
9090
>m2 : () => Promise<void>
9191

9292
async m3(): MyPromise<void> { }
93-
>m3 : () => Promise<void>
93+
>m3 : () => MyPromise<void>
9494

9595
static async m4() { }
9696
>m4 : () => Promise<void>
@@ -99,7 +99,7 @@ class C {
9999
>m5 : () => Promise<void>
100100

101101
static async m6(): MyPromise<void> { }
102-
>m6 : () => Promise<void>
102+
>m6 : () => MyPromise<void>
103103
}
104104

105105
module M {

tests/baselines/reference/asyncAwait_es5.types

+16-16
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
=== tests/cases/conformance/async/es5/asyncAwait_es5.ts ===
22
type MyPromise<T> = Promise<T>;
3-
>MyPromise : Promise<T>
3+
>MyPromise : MyPromise<T>
44

55
declare var MyPromise: typeof Promise;
66
>MyPromise : PromiseConstructor
@@ -10,7 +10,7 @@ declare var p: Promise<number>;
1010
>p : Promise<number>
1111

1212
declare var mp: MyPromise<number>;
13-
>mp : Promise<number>
13+
>mp : MyPromise<number>
1414

1515
async function f0() { }
1616
>f0 : () => Promise<void>
@@ -19,7 +19,7 @@ async function f1(): Promise<void> { }
1919
>f1 : () => Promise<void>
2020

2121
async function f3(): MyPromise<void> { }
22-
>f3 : () => Promise<void>
22+
>f3 : () => MyPromise<void>
2323

2424
let f4 = async function() { }
2525
>f4 : () => Promise<void>
@@ -30,8 +30,8 @@ let f5 = async function(): Promise<void> { }
3030
>async function(): Promise<void> { } : () => Promise<void>
3131

3232
let f6 = async function(): MyPromise<void> { }
33-
>f6 : () => Promise<void>
34-
>async function(): MyPromise<void> { } : () => Promise<void>
33+
>f6 : () => MyPromise<void>
34+
>async function(): MyPromise<void> { } : () => MyPromise<void>
3535

3636
let f7 = async () => { };
3737
>f7 : () => Promise<void>
@@ -42,8 +42,8 @@ let f8 = async (): Promise<void> => { };
4242
>async (): Promise<void> => { } : () => Promise<void>
4343

4444
let f9 = async (): MyPromise<void> => { };
45-
>f9 : () => Promise<void>
46-
>async (): MyPromise<void> => { } : () => Promise<void>
45+
>f9 : () => MyPromise<void>
46+
>async (): MyPromise<void> => { } : () => MyPromise<void>
4747

4848
let f10 = async () => p;
4949
>f10 : () => Promise<number>
@@ -53,21 +53,21 @@ let f10 = async () => p;
5353
let f11 = async () => mp;
5454
>f11 : () => Promise<number>
5555
>async () => mp : () => Promise<number>
56-
>mp : Promise<number>
56+
>mp : MyPromise<number>
5757

5858
let f12 = async (): Promise<number> => mp;
5959
>f12 : () => Promise<number>
6060
>async (): Promise<number> => mp : () => Promise<number>
61-
>mp : Promise<number>
61+
>mp : MyPromise<number>
6262

6363
let f13 = async (): MyPromise<number> => p;
64-
>f13 : () => Promise<number>
65-
>async (): MyPromise<number> => p : () => Promise<number>
64+
>f13 : () => MyPromise<number>
65+
>async (): MyPromise<number> => p : () => MyPromise<number>
6666
>p : Promise<number>
6767

6868
let o = {
69-
>o : { m1(): Promise<void>; m2(): Promise<void>; m3(): Promise<void>; }
70-
>{ async m1() { }, async m2(): Promise<void> { }, async m3(): MyPromise<void> { }} : { m1(): Promise<void>; m2(): Promise<void>; m3(): Promise<void>; }
69+
>o : { m1(): Promise<void>; m2(): Promise<void>; m3(): MyPromise<void>; }
70+
>{ async m1() { }, async m2(): Promise<void> { }, async m3(): MyPromise<void> { }} : { m1(): Promise<void>; m2(): Promise<void>; m3(): MyPromise<void>; }
7171

7272
async m1() { },
7373
>m1 : () => Promise<void>
@@ -76,7 +76,7 @@ let o = {
7676
>m2 : () => Promise<void>
7777

7878
async m3(): MyPromise<void> { }
79-
>m3 : () => Promise<void>
79+
>m3 : () => MyPromise<void>
8080

8181
};
8282

@@ -90,7 +90,7 @@ class C {
9090
>m2 : () => Promise<void>
9191

9292
async m3(): MyPromise<void> { }
93-
>m3 : () => Promise<void>
93+
>m3 : () => MyPromise<void>
9494

9595
static async m4() { }
9696
>m4 : () => Promise<void>
@@ -99,7 +99,7 @@ class C {
9999
>m5 : () => Promise<void>
100100

101101
static async m6(): MyPromise<void> { }
102-
>m6 : () => Promise<void>
102+
>m6 : () => MyPromise<void>
103103
}
104104

105105
module M {

0 commit comments

Comments
 (0)