Skip to content

Commit b8ebad4

Browse files
authored
Fix recursive types in @typedef (#40861)
* Fix reference types in @typedef Previously this code path was broken and untested. Fortunately the fix is simple. * add test case from #40234 * update baselines
1 parent 0ba250d commit b8ebad4

32 files changed

+358
-150
lines changed

src/compiler/checker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14398,7 +14398,7 @@ namespace ts {
1439814398

1439914399
function getAliasSymbolForTypeNode(node: Node) {
1440014400
let host = node.parent;
14401-
while (isParenthesizedTypeNode(host) || isTypeOperatorNode(host) && host.operator === SyntaxKind.ReadonlyKeyword) {
14401+
while (isParenthesizedTypeNode(host) || isJSDocTypeExpression(host) || isTypeOperatorNode(host) && host.operator === SyntaxKind.ReadonlyKeyword) {
1440214402
host = host.parent;
1440314403
}
1440414404
return isTypeAlias(host) ? getSymbolOfNode(host) : undefined;

tests/baselines/reference/assertionsAndNonReturningFunctions.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
/** @type {AssertFunc} */
55
const assert = check => {
6-
>assert : (check: boolean) => asserts check
6+
>assert : AssertFunc
77
>check => { if (!check) throw new Error();} : (check: boolean) => asserts check
88
>check : boolean
99

@@ -70,7 +70,7 @@ function f1(x) {
7070

7171
assert(typeof x === "string");
7272
>assert(typeof x === "string") : void
73-
>assert : (check: boolean) => asserts check
73+
>assert : AssertFunc
7474
>typeof x === "string" : boolean
7575
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
7676
>x : any

tests/baselines/reference/checkJsTypeDefNoUnusedLocalMarked.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ module.exports = /** @type {FooFun} */(void 0);
2626
>module.exports : (foo: typeof import("tests/cases/compiler/file")) => string
2727
>module : { "\"tests/cases/compiler/something\"": (foo: typeof import("tests/cases/compiler/file")) => string; }
2828
>exports : (foo: typeof import("tests/cases/compiler/file")) => string
29-
>(void 0) : (foo: typeof import("tests/cases/compiler/file")) => string
29+
>(void 0) : FooFun
3030
>void 0 : undefined
3131
>0 : 0
3232

tests/baselines/reference/checkJsdocTypeTag4.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@ var a;
1414

1515
/** @type {B<number>} */
1616
var b;
17-
>b : { b: number; }
17+
>b : B<number>
1818

tests/baselines/reference/contextualTypedSpecialAssignment.types

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ var ns = {}
1212
/** @type {DoneStatus} */
1313
ns.x = {
1414
>ns.x = { status: 'done', m(n) { }} : { status: "done"; m(n: number): void; }
15-
>ns.x : { status: "done"; m(n: number): void; }
15+
>ns.x : DoneStatus
1616
>ns : typeof ns
17-
>x : { status: "done"; m(n: number): void; }
17+
>x : DoneStatus
1818
>{ status: 'done', m(n) { }} : { status: "done"; m(n: number): void; }
1919

2020
status: 'done',
@@ -28,9 +28,9 @@ ns.x = {
2828

2929
ns.x = {
3030
>ns.x = { status: 'done', m(n) { }} : { status: "done"; m(n: number): void; }
31-
>ns.x : { status: "done"; m(n: number): void; }
31+
>ns.x : DoneStatus
3232
>ns : typeof ns
33-
>x : { status: "done"; m(n: number): void; }
33+
>x : DoneStatus
3434
>{ status: 'done', m(n) { }} : { status: "done"; m(n: number): void; }
3535

3636
status: 'done',
@@ -42,9 +42,9 @@ ns.x = {
4242
>n : number
4343
}
4444
ns.x
45-
>ns.x : { status: "done"; m(n: number): void; }
45+
>ns.x : DoneStatus
4646
>ns : typeof ns
47-
>x : { status: "done"; m(n: number): void; }
47+
>x : DoneStatus
4848

4949

5050
// this-property assignment
@@ -55,9 +55,9 @@ class Thing {
5555
/** @type {DoneStatus} */
5656
this.s = {
5757
>this.s = { status: 'done', m(n) { } } : { status: "done"; m(n: number): void; }
58-
>this.s : { status: "done"; m(n: number): void; }
58+
>this.s : DoneStatus
5959
>this : this
60-
>s : { status: "done"; m(n: number): void; }
60+
>s : DoneStatus
6161
>{ status: 'done', m(n) { } } : { status: "done"; m(n: number): void; }
6262

6363
status: 'done',
@@ -75,9 +75,9 @@ class Thing {
7575

7676
this.s = {
7777
>this.s = { status: 'done', m(n) { } } : { status: "done"; m(n: number): void; }
78-
>this.s : { status: "done"; m(n: number): void; }
78+
>this.s : DoneStatus
7979
>this : this
80-
>s : { status: "done"; m(n: number): void; }
80+
>s : DoneStatus
8181
>{ status: 'done', m(n) { } } : { status: "done"; m(n: number): void; }
8282

8383
status: 'done',
@@ -96,9 +96,9 @@ class Thing {
9696
/** @type {DoneStatus} */
9797
exports.x = {
9898
>exports.x = { status: "done", m(n) { }} : { status: "done"; m(n: number): void; }
99-
>exports.x : { status: "done"; m(n: number): void; }
99+
>exports.x : DoneStatus
100100
>exports : typeof import("tests/cases/conformance/salsa/test")
101-
>x : { status: "done"; m(n: number): void; }
101+
>x : DoneStatus
102102
>{ status: "done", m(n) { }} : { status: "done"; m(n: number): void; }
103103

104104
status: "done",
@@ -110,18 +110,18 @@ exports.x = {
110110
>n : number
111111
}
112112
exports.x
113-
>exports.x : { status: "done"; m(n: number): void; }
113+
>exports.x : DoneStatus
114114
>exports : typeof import("tests/cases/conformance/salsa/test")
115-
>x : { status: "done"; m(n: number): void; }
115+
>x : DoneStatus
116116

117117
/** @type {DoneStatus} */
118118
module.exports.y = {
119119
>module.exports.y = { status: "done", m(n) { }} : { status: "done"; m(n: number): void; }
120-
>module.exports.y : { status: "done"; m(n: number): void; }
120+
>module.exports.y : DoneStatus
121121
>module.exports : typeof import("tests/cases/conformance/salsa/test")
122122
>module : { "\"tests/cases/conformance/salsa/test\"": typeof import("tests/cases/conformance/salsa/test"); }
123123
>exports : typeof import("tests/cases/conformance/salsa/test")
124-
>y : { status: "done"; m(n: number): void; }
124+
>y : DoneStatus
125125
>{ status: "done", m(n) { }} : { status: "done"; m(n: number): void; }
126126

127127
status: "done",
@@ -133,21 +133,21 @@ module.exports.y = {
133133
>n : number
134134
}
135135
module.exports.y
136-
>module.exports.y : { status: "done"; m(n: number): void; }
136+
>module.exports.y : DoneStatus
137137
>module.exports : typeof import("tests/cases/conformance/salsa/test")
138138
>module : { "\"tests/cases/conformance/salsa/test\"": typeof import("tests/cases/conformance/salsa/test"); }
139139
>exports : typeof import("tests/cases/conformance/salsa/test")
140-
>y : { status: "done"; m(n: number): void; }
140+
>y : DoneStatus
141141

142142
// prototype-property assignment
143143
/** @type {DoneStatus} */
144144
Thing.prototype.x = {
145145
>Thing.prototype.x = { status: 'done', m(n) { }} : { status: "done"; m(n: number): void; }
146-
>Thing.prototype.x : { status: "done"; m(n: number): void; }
146+
>Thing.prototype.x : DoneStatus
147147
>Thing.prototype : Thing
148148
>Thing : typeof Thing
149149
>prototype : Thing
150-
>x : { status: "done"; m(n: number): void; }
150+
>x : DoneStatus
151151
>{ status: 'done', m(n) { }} : { status: "done"; m(n: number): void; }
152152

153153
status: 'done',
@@ -159,11 +159,11 @@ Thing.prototype.x = {
159159
>n : number
160160
}
161161
Thing.prototype.x
162-
>Thing.prototype.x : { status: "done"; m(n: number): void; }
162+
>Thing.prototype.x : DoneStatus
163163
>Thing.prototype : Thing
164164
>Thing : typeof Thing
165165
>prototype : Thing
166-
>x : { status: "done"; m(n: number): void; }
166+
>x : DoneStatus
167167

168168
// prototype assignment
169169
function F() {
@@ -172,9 +172,9 @@ function F() {
172172
/** @type {DoneStatus} */
173173
F.prototype = {
174174
>F.prototype = { status: "done", m(n) { }} : { status: "done"; m(n: number): void; }
175-
>F.prototype : { status: "done"; m(n: number): void; }
175+
>F.prototype : DoneStatus
176176
>F : typeof F
177-
>prototype : { status: "done"; m(n: number): void; }
177+
>prototype : DoneStatus
178178
>{ status: "done", m(n) { }} : { status: "done"; m(n: number): void; }
179179

180180
status: "done",

tests/baselines/reference/enumTag.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ function consume(t,s,f) {
7979
>consume : (t: Target, s: Second, f: Fs) => void
8080
>t : string
8181
>s : number
82-
>f : (arg0: number) => number
82+
>f : Fs
8383

8484
/** @type {string} */
8585
var str = t
@@ -94,7 +94,7 @@ function consume(t,s,f) {
9494
/** @type {(n: number) => number} */
9595
var fun = f
9696
>fun : (n: number) => number
97-
>f : (arg0: number) => number
97+
>f : Fs
9898

9999
/** @type {Target} */
100100
var v = Target.START

tests/baselines/reference/expandoFunctionContextualTypesJs.types

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@
99
* @type {StatelessComponent<MyComponentProps>}
1010
*/
1111
const MyComponent = () => /* @type {any} */(null);
12-
>MyComponent : { (): any; defaultProps?: Partial<{ color: "red" | "blue"; }>; }
13-
>() => /* @type {any} */(null) : { (): any; defaultProps: Partial<{ color: "red" | "blue"; }>; }
12+
>MyComponent : StatelessComponent<MyComponentProps>
13+
>() => /* @type {any} */(null) : { (): any; defaultProps: Partial<MyComponentProps>; }
1414
>(null) : null
1515
>null : null
1616

1717
MyComponent.defaultProps = {
1818
>MyComponent.defaultProps = { color: "red"} : { color: "red"; }
19-
>MyComponent.defaultProps : Partial<{ color: "red" | "blue"; }>
20-
>MyComponent : { (): any; defaultProps?: Partial<{ color: "red" | "blue"; }>; }
21-
>defaultProps : Partial<{ color: "red" | "blue"; }>
19+
>MyComponent.defaultProps : Partial<MyComponentProps>
20+
>MyComponent : StatelessComponent<MyComponentProps>
21+
>defaultProps : Partial<MyComponentProps>
2222
>{ color: "red"} : { color: "red"; }
2323

2424
color: "red"
@@ -28,18 +28,18 @@ MyComponent.defaultProps = {
2828
};
2929

3030
const MyComponent2 = () => null;
31-
>MyComponent2 : { (): any; defaultProps: { color: "red" | "blue"; }; }
32-
>() => null : { (): any; defaultProps: { color: "red" | "blue"; }; }
31+
>MyComponent2 : { (): any; defaultProps: MyComponentProps; }
32+
>() => null : { (): any; defaultProps: MyComponentProps; }
3333
>null : null
3434

3535
/**
3636
* @type {MyComponentProps}
3737
*/
3838
MyComponent2.defaultProps = {
3939
>MyComponent2.defaultProps = { color: "red"} : { color: "red"; }
40-
>MyComponent2.defaultProps : { color: "red" | "blue"; }
40+
>MyComponent2.defaultProps : MyComponentProps
4141
>MyComponent2 : { (): any; defaultProps: MyComponentProps; }
42-
>defaultProps : { color: "red" | "blue"; }
42+
>defaultProps : MyComponentProps
4343
>{ color: "red"} : { color: "red"; }
4444

4545
color: "red"
@@ -51,16 +51,16 @@ MyComponent2.defaultProps = {
5151
* @type {StatelessComponent<MyComponentProps>}
5252
*/
5353
const check = MyComponent2;
54-
>check : { (): any; defaultProps?: Partial<{ color: "red" | "blue"; }>; }
55-
>MyComponent2 : { (): any; defaultProps: { color: "red" | "blue"; }; }
54+
>check : StatelessComponent<MyComponentProps>
55+
>MyComponent2 : { (): any; defaultProps: MyComponentProps; }
5656

5757
/**
5858
*
5959
* @param {{ props: MyComponentProps }} p
6060
*/
6161
function expectLiteral(p) {}
6262
>expectLiteral : (p: { props: MyComponentProps;}) => void
63-
>p : { props: { color: "red" | "blue"; }; }
63+
>p : { props: MyComponentProps; }
6464

6565
function foo() {
6666
>foo : typeof foo
@@ -70,27 +70,27 @@ function foo() {
7070
*/
7171
this.props = { color: "red" };
7272
>this.props = { color: "red" } : { color: "red"; }
73-
>this.props : { color: "red" | "blue"; }
73+
>this.props : MyComponentProps
7474
>this : this
75-
>props : { color: "red" | "blue"; }
75+
>props : MyComponentProps
7676
>{ color: "red" } : { color: "red"; }
7777
>color : "red"
7878
>"red" : "red"
7979

8080
expectLiteral(this);
8181
>expectLiteral(this) : void
82-
>expectLiteral : (p: { props: { color: "red" | "blue"; }; }) => void
82+
>expectLiteral : (p: { props: MyComponentProps; }) => void
8383
>this : this
8484
}
8585

8686
/**
8787
* @type {MyComponentProps}
8888
*/
8989
module.exports = {
90-
>module.exports = { color: "red"} : { color: "red" | "blue"; }
91-
>module.exports : { color: "red" | "blue"; }
92-
>module : { "\"tests/cases/compiler/input\"": { color: "red" | "blue"; }; }
93-
>exports : { color: "red" | "blue"; }
90+
>module.exports = { color: "red"} : MyComponentProps
91+
>module.exports : MyComponentProps
92+
>module : { "\"tests/cases/compiler/input\"": MyComponentProps; }
93+
>exports : MyComponentProps
9494
>{ color: "red"} : { color: "red"; }
9595

9696
color: "red"
@@ -100,10 +100,10 @@ module.exports = {
100100

101101
expectLiteral({ props: module.exports });
102102
>expectLiteral({ props: module.exports }) : void
103-
>expectLiteral : (p: { props: { color: "red" | "blue"; }; }) => void
104-
>{ props: module.exports } : { props: { color: "red" | "blue"; }; }
105-
>props : { color: "red" | "blue"; }
106-
>module.exports : { color: "red" | "blue"; }
107-
>module : { "\"tests/cases/compiler/input\"": { color: "red" | "blue"; }; }
108-
>exports : { color: "red" | "blue"; }
103+
>expectLiteral : (p: { props: MyComponentProps; }) => void
104+
>{ props: module.exports } : { props: MyComponentProps; }
105+
>props : MyComponentProps
106+
>module.exports : MyComponentProps
107+
>module : { "\"tests/cases/compiler/input\"": MyComponentProps; }
108+
>exports : MyComponentProps
109109

tests/baselines/reference/exportDefaultWithJSDoc1.types

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@
55
*/
66

77
/** @type {NumberLike[]} */export default ([ ]);
8-
>([ ]) : (string | number)[]
8+
>([ ]) : NumberLike[]
99
>[ ] : undefined[]
1010

1111
=== tests/cases/compiler/b.ts ===
1212
import A from './a'
13-
>A : (string | number)[]
13+
>A : import("tests/cases/compiler/a").NumberLike[]
1414

1515
A[0]
16-
>A[0] : string | number
17-
>A : (string | number)[]
16+
>A[0] : import("tests/cases/compiler/a").NumberLike
17+
>A : import("tests/cases/compiler/a").NumberLike[]
1818
>0 : 0
1919

tests/baselines/reference/exportDefaultWithJSDoc2.types

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@
55
*/
66

77
export default /** @type {NumberLike[]} */([ ]);
8-
>([ ]) : (string | number)[]
8+
>([ ]) : NumberLike[]
99
>[ ] : undefined[]
1010

1111
=== tests/cases/compiler/b.ts ===
1212
import A from './a'
13-
>A : (string | number)[]
13+
>A : import("tests/cases/compiler/a").NumberLike[]
1414

1515
A[0]
16-
>A[0] : string | number
17-
>A : (string | number)[]
16+
>A[0] : import("tests/cases/compiler/a").NumberLike
17+
>A : import("tests/cases/compiler/a").NumberLike[]
1818
>0 : 0
1919

tests/baselines/reference/jsDeclarationsEnumTag.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export function consume(t,s,f) {
7272
>consume : (t: Target, s: Second, f: Fs) => void
7373
>t : string
7474
>s : number
75-
>f : (arg0: number) => number
75+
>f : Fs
7676

7777
/** @type {string} */
7878
var str = t
@@ -87,7 +87,7 @@ export function consume(t,s,f) {
8787
/** @type {(n: number) => number} */
8888
var fun = f
8989
>fun : (n: number) => number
90-
>f : (arg0: number) => number
90+
>f : Fs
9191

9292
/** @type {Target} */
9393
var v = Target.START

tests/baselines/reference/jsDeclarationsFunctionClassesCjsExportAssignment.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ declare class Hook {
264264
* @param {HookHandler} handle
265265
*/
266266
constructor(handle: HookHandler);
267-
handle: (arg: import("./context")) => void;
267+
handle: HookHandler;
268268
}
269269
declare namespace Hook {
270270
export { HookHandler };

0 commit comments

Comments
 (0)