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
This commit is contained in:
Nathan Shively-Sanders
2020-10-02 08:46:42 -07:00
committed by GitHub
parent 0ba250dc3b
commit b8ebad48d7
32 changed files with 358 additions and 150 deletions
+1 -1
View File
@@ -14398,7 +14398,7 @@ namespace ts {
function getAliasSymbolForTypeNode(node: Node) {
let host = node.parent;
while (isParenthesizedTypeNode(host) || isTypeOperatorNode(host) && host.operator === SyntaxKind.ReadonlyKeyword) {
while (isParenthesizedTypeNode(host) || isJSDocTypeExpression(host) || isTypeOperatorNode(host) && host.operator === SyntaxKind.ReadonlyKeyword) {
host = host.parent;
}
return isTypeAlias(host) ? getSymbolOfNode(host) : undefined;
@@ -3,7 +3,7 @@
/** @type {AssertFunc} */
const assert = check => {
>assert : (check: boolean) => asserts check
>assert : AssertFunc
>check => { if (!check) throw new Error();} : (check: boolean) => asserts check
>check : boolean
@@ -70,7 +70,7 @@ function f1(x) {
assert(typeof x === "string");
>assert(typeof x === "string") : void
>assert : (check: boolean) => asserts check
>assert : AssertFunc
>typeof x === "string" : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : any
@@ -26,7 +26,7 @@ module.exports = /** @type {FooFun} */(void 0);
>module.exports : (foo: typeof import("tests/cases/compiler/file")) => string
>module : { "\"tests/cases/compiler/something\"": (foo: typeof import("tests/cases/compiler/file")) => string; }
>exports : (foo: typeof import("tests/cases/compiler/file")) => string
>(void 0) : (foo: typeof import("tests/cases/compiler/file")) => string
>(void 0) : FooFun
>void 0 : undefined
>0 : 0
@@ -14,5 +14,5 @@ var a;
/** @type {B<number>} */
var b;
>b : { b: number; }
>b : B<number>
@@ -12,9 +12,9 @@ var ns = {}
/** @type {DoneStatus} */
ns.x = {
>ns.x = { status: 'done', m(n) { }} : { status: "done"; m(n: number): void; }
>ns.x : { status: "done"; m(n: number): void; }
>ns.x : DoneStatus
>ns : typeof ns
>x : { status: "done"; m(n: number): void; }
>x : DoneStatus
>{ status: 'done', m(n) { }} : { status: "done"; m(n: number): void; }
status: 'done',
@@ -28,9 +28,9 @@ ns.x = {
ns.x = {
>ns.x = { status: 'done', m(n) { }} : { status: "done"; m(n: number): void; }
>ns.x : { status: "done"; m(n: number): void; }
>ns.x : DoneStatus
>ns : typeof ns
>x : { status: "done"; m(n: number): void; }
>x : DoneStatus
>{ status: 'done', m(n) { }} : { status: "done"; m(n: number): void; }
status: 'done',
@@ -42,9 +42,9 @@ ns.x = {
>n : number
}
ns.x
>ns.x : { status: "done"; m(n: number): void; }
>ns.x : DoneStatus
>ns : typeof ns
>x : { status: "done"; m(n: number): void; }
>x : DoneStatus
// this-property assignment
@@ -55,9 +55,9 @@ class Thing {
/** @type {DoneStatus} */
this.s = {
>this.s = { status: 'done', m(n) { } } : { status: "done"; m(n: number): void; }
>this.s : { status: "done"; m(n: number): void; }
>this.s : DoneStatus
>this : this
>s : { status: "done"; m(n: number): void; }
>s : DoneStatus
>{ status: 'done', m(n) { } } : { status: "done"; m(n: number): void; }
status: 'done',
@@ -75,9 +75,9 @@ class Thing {
this.s = {
>this.s = { status: 'done', m(n) { } } : { status: "done"; m(n: number): void; }
>this.s : { status: "done"; m(n: number): void; }
>this.s : DoneStatus
>this : this
>s : { status: "done"; m(n: number): void; }
>s : DoneStatus
>{ status: 'done', m(n) { } } : { status: "done"; m(n: number): void; }
status: 'done',
@@ -96,9 +96,9 @@ class Thing {
/** @type {DoneStatus} */
exports.x = {
>exports.x = { status: "done", m(n) { }} : { status: "done"; m(n: number): void; }
>exports.x : { status: "done"; m(n: number): void; }
>exports.x : DoneStatus
>exports : typeof import("tests/cases/conformance/salsa/test")
>x : { status: "done"; m(n: number): void; }
>x : DoneStatus
>{ status: "done", m(n) { }} : { status: "done"; m(n: number): void; }
status: "done",
@@ -110,18 +110,18 @@ exports.x = {
>n : number
}
exports.x
>exports.x : { status: "done"; m(n: number): void; }
>exports.x : DoneStatus
>exports : typeof import("tests/cases/conformance/salsa/test")
>x : { status: "done"; m(n: number): void; }
>x : DoneStatus
/** @type {DoneStatus} */
module.exports.y = {
>module.exports.y = { status: "done", m(n) { }} : { status: "done"; m(n: number): void; }
>module.exports.y : { status: "done"; m(n: number): void; }
>module.exports.y : DoneStatus
>module.exports : typeof import("tests/cases/conformance/salsa/test")
>module : { "\"tests/cases/conformance/salsa/test\"": typeof import("tests/cases/conformance/salsa/test"); }
>exports : typeof import("tests/cases/conformance/salsa/test")
>y : { status: "done"; m(n: number): void; }
>y : DoneStatus
>{ status: "done", m(n) { }} : { status: "done"; m(n: number): void; }
status: "done",
@@ -133,21 +133,21 @@ module.exports.y = {
>n : number
}
module.exports.y
>module.exports.y : { status: "done"; m(n: number): void; }
>module.exports.y : DoneStatus
>module.exports : typeof import("tests/cases/conformance/salsa/test")
>module : { "\"tests/cases/conformance/salsa/test\"": typeof import("tests/cases/conformance/salsa/test"); }
>exports : typeof import("tests/cases/conformance/salsa/test")
>y : { status: "done"; m(n: number): void; }
>y : DoneStatus
// prototype-property assignment
/** @type {DoneStatus} */
Thing.prototype.x = {
>Thing.prototype.x = { status: 'done', m(n) { }} : { status: "done"; m(n: number): void; }
>Thing.prototype.x : { status: "done"; m(n: number): void; }
>Thing.prototype.x : DoneStatus
>Thing.prototype : Thing
>Thing : typeof Thing
>prototype : Thing
>x : { status: "done"; m(n: number): void; }
>x : DoneStatus
>{ status: 'done', m(n) { }} : { status: "done"; m(n: number): void; }
status: 'done',
@@ -159,11 +159,11 @@ Thing.prototype.x = {
>n : number
}
Thing.prototype.x
>Thing.prototype.x : { status: "done"; m(n: number): void; }
>Thing.prototype.x : DoneStatus
>Thing.prototype : Thing
>Thing : typeof Thing
>prototype : Thing
>x : { status: "done"; m(n: number): void; }
>x : DoneStatus
// prototype assignment
function F() {
@@ -172,9 +172,9 @@ function F() {
/** @type {DoneStatus} */
F.prototype = {
>F.prototype = { status: "done", m(n) { }} : { status: "done"; m(n: number): void; }
>F.prototype : { status: "done"; m(n: number): void; }
>F.prototype : DoneStatus
>F : typeof F
>prototype : { status: "done"; m(n: number): void; }
>prototype : DoneStatus
>{ status: "done", m(n) { }} : { status: "done"; m(n: number): void; }
status: "done",
+2 -2
View File
@@ -79,7 +79,7 @@ function consume(t,s,f) {
>consume : (t: Target, s: Second, f: Fs) => void
>t : string
>s : number
>f : (arg0: number) => number
>f : Fs
/** @type {string} */
var str = t
@@ -94,7 +94,7 @@ function consume(t,s,f) {
/** @type {(n: number) => number} */
var fun = f
>fun : (n: number) => number
>f : (arg0: number) => number
>f : Fs
/** @type {Target} */
var v = Target.START
@@ -9,16 +9,16 @@
* @type {StatelessComponent<MyComponentProps>}
*/
const MyComponent = () => /* @type {any} */(null);
>MyComponent : { (): any; defaultProps?: Partial<{ color: "red" | "blue"; }>; }
>() => /* @type {any} */(null) : { (): any; defaultProps: Partial<{ color: "red" | "blue"; }>; }
>MyComponent : StatelessComponent<MyComponentProps>
>() => /* @type {any} */(null) : { (): any; defaultProps: Partial<MyComponentProps>; }
>(null) : null
>null : null
MyComponent.defaultProps = {
>MyComponent.defaultProps = { color: "red"} : { color: "red"; }
>MyComponent.defaultProps : Partial<{ color: "red" | "blue"; }>
>MyComponent : { (): any; defaultProps?: Partial<{ color: "red" | "blue"; }>; }
>defaultProps : Partial<{ color: "red" | "blue"; }>
>MyComponent.defaultProps : Partial<MyComponentProps>
>MyComponent : StatelessComponent<MyComponentProps>
>defaultProps : Partial<MyComponentProps>
>{ color: "red"} : { color: "red"; }
color: "red"
@@ -28,8 +28,8 @@ MyComponent.defaultProps = {
};
const MyComponent2 = () => null;
>MyComponent2 : { (): any; defaultProps: { color: "red" | "blue"; }; }
>() => null : { (): any; defaultProps: { color: "red" | "blue"; }; }
>MyComponent2 : { (): any; defaultProps: MyComponentProps; }
>() => null : { (): any; defaultProps: MyComponentProps; }
>null : null
/**
@@ -37,9 +37,9 @@ const MyComponent2 = () => null;
*/
MyComponent2.defaultProps = {
>MyComponent2.defaultProps = { color: "red"} : { color: "red"; }
>MyComponent2.defaultProps : { color: "red" | "blue"; }
>MyComponent2.defaultProps : MyComponentProps
>MyComponent2 : { (): any; defaultProps: MyComponentProps; }
>defaultProps : { color: "red" | "blue"; }
>defaultProps : MyComponentProps
>{ color: "red"} : { color: "red"; }
color: "red"
@@ -51,8 +51,8 @@ MyComponent2.defaultProps = {
* @type {StatelessComponent<MyComponentProps>}
*/
const check = MyComponent2;
>check : { (): any; defaultProps?: Partial<{ color: "red" | "blue"; }>; }
>MyComponent2 : { (): any; defaultProps: { color: "red" | "blue"; }; }
>check : StatelessComponent<MyComponentProps>
>MyComponent2 : { (): any; defaultProps: MyComponentProps; }
/**
*
@@ -60,7 +60,7 @@ const check = MyComponent2;
*/
function expectLiteral(p) {}
>expectLiteral : (p: { props: MyComponentProps;}) => void
>p : { props: { color: "red" | "blue"; }; }
>p : { props: MyComponentProps; }
function foo() {
>foo : typeof foo
@@ -70,16 +70,16 @@ function foo() {
*/
this.props = { color: "red" };
>this.props = { color: "red" } : { color: "red"; }
>this.props : { color: "red" | "blue"; }
>this.props : MyComponentProps
>this : this
>props : { color: "red" | "blue"; }
>props : MyComponentProps
>{ color: "red" } : { color: "red"; }
>color : "red"
>"red" : "red"
expectLiteral(this);
>expectLiteral(this) : void
>expectLiteral : (p: { props: { color: "red" | "blue"; }; }) => void
>expectLiteral : (p: { props: MyComponentProps; }) => void
>this : this
}
@@ -87,10 +87,10 @@ function foo() {
* @type {MyComponentProps}
*/
module.exports = {
>module.exports = { color: "red"} : { color: "red" | "blue"; }
>module.exports : { color: "red" | "blue"; }
>module : { "\"tests/cases/compiler/input\"": { color: "red" | "blue"; }; }
>exports : { color: "red" | "blue"; }
>module.exports = { color: "red"} : MyComponentProps
>module.exports : MyComponentProps
>module : { "\"tests/cases/compiler/input\"": MyComponentProps; }
>exports : MyComponentProps
>{ color: "red"} : { color: "red"; }
color: "red"
@@ -100,10 +100,10 @@ module.exports = {
expectLiteral({ props: module.exports });
>expectLiteral({ props: module.exports }) : void
>expectLiteral : (p: { props: { color: "red" | "blue"; }; }) => void
>{ props: module.exports } : { props: { color: "red" | "blue"; }; }
>props : { color: "red" | "blue"; }
>module.exports : { color: "red" | "blue"; }
>module : { "\"tests/cases/compiler/input\"": { color: "red" | "blue"; }; }
>exports : { color: "red" | "blue"; }
>expectLiteral : (p: { props: MyComponentProps; }) => void
>{ props: module.exports } : { props: MyComponentProps; }
>props : MyComponentProps
>module.exports : MyComponentProps
>module : { "\"tests/cases/compiler/input\"": MyComponentProps; }
>exports : MyComponentProps
@@ -5,15 +5,15 @@
*/
/** @type {NumberLike[]} */export default ([ ]);
>([ ]) : (string | number)[]
>([ ]) : NumberLike[]
>[ ] : undefined[]
=== tests/cases/compiler/b.ts ===
import A from './a'
>A : (string | number)[]
>A : import("tests/cases/compiler/a").NumberLike[]
A[0]
>A[0] : string | number
>A : (string | number)[]
>A[0] : import("tests/cases/compiler/a").NumberLike
>A : import("tests/cases/compiler/a").NumberLike[]
>0 : 0
@@ -5,15 +5,15 @@
*/
export default /** @type {NumberLike[]} */([ ]);
>([ ]) : (string | number)[]
>([ ]) : NumberLike[]
>[ ] : undefined[]
=== tests/cases/compiler/b.ts ===
import A from './a'
>A : (string | number)[]
>A : import("tests/cases/compiler/a").NumberLike[]
A[0]
>A[0] : string | number
>A : (string | number)[]
>A[0] : import("tests/cases/compiler/a").NumberLike
>A : import("tests/cases/compiler/a").NumberLike[]
>0 : 0
@@ -72,7 +72,7 @@ export function consume(t,s,f) {
>consume : (t: Target, s: Second, f: Fs) => void
>t : string
>s : number
>f : (arg0: number) => number
>f : Fs
/** @type {string} */
var str = t
@@ -87,7 +87,7 @@ export function consume(t,s,f) {
/** @type {(n: number) => number} */
var fun = f
>fun : (n: number) => number
>f : (arg0: number) => number
>f : Fs
/** @type {Target} */
var v = Target.START
@@ -264,7 +264,7 @@ declare class Hook {
* @param {HookHandler} handle
*/
constructor(handle: HookHandler);
handle: (arg: import("./context")) => void;
handle: HookHandler;
}
declare namespace Hook {
export { HookHandler };
@@ -29,14 +29,14 @@ module.exports = Timer;
*/
function Hook(handle) {
>Hook : typeof Hook
>handle : (arg: import("tests/cases/conformance/jsdoc/declarations/context")) => void
>handle : HookHandler
this.handle = handle;
>this.handle = handle : (arg: import("tests/cases/conformance/jsdoc/declarations/context")) => void
>this.handle = handle : HookHandler
>this.handle : any
>this : this
>handle : any
>handle : (arg: import("tests/cases/conformance/jsdoc/declarations/context")) => void
>handle : HookHandler
}
module.exports = Hook;
>module.exports = Hook : typeof Hook
@@ -96,19 +96,19 @@ function Context(input) {
this.state = this.construct(input);
>this.state = this.construct(input) : State
>this.state : any
>this : this & { construct(input: Input, handle?: (arg: Context) => void): State; }
>this : this & { construct(input: Input, handle?: import("tests/cases/conformance/jsdoc/declarations/hook").HookHandler): State; }
>state : any
>this.construct(input) : State
>this.construct : (input: Input, handle?: (arg: Context) => void) => State
>this : this & { construct(input: Input, handle?: (arg: Context) => void): State; }
>construct : (input: Input, handle?: (arg: Context) => void) => State
>this.construct : (input: Input, handle?: import("tests/cases/conformance/jsdoc/declarations/hook").HookHandler) => State
>this : this & { construct(input: Input, handle?: import("tests/cases/conformance/jsdoc/declarations/hook").HookHandler): State; }
>construct : (input: Input, handle?: import("tests/cases/conformance/jsdoc/declarations/hook").HookHandler) => State
>input : Input
}
Context.prototype = {
>Context.prototype = { /** * @param {Input} input * @param {HookHandler=} handle * @returns {State} */ construct(input, handle = () => void 0) { return input; }} : { construct(input: Input, handle?: HookHandler | undefined): State; }
>Context.prototype : { construct(input: Input, handle?: HookHandler | undefined): State; }
>Context : typeof Context
>prototype : { construct(input: Input, handle?: (arg: Context) => void): State; }
>prototype : { construct(input: Input, handle?: import("tests/cases/conformance/jsdoc/declarations/hook").HookHandler): State; }
>{ /** * @param {Input} input * @param {HookHandler=} handle * @returns {State} */ construct(input, handle = () => void 0) { return input; }} : { construct(input: Input, handle?: HookHandler | undefined): State; }
/**
@@ -119,7 +119,7 @@ Context.prototype = {
construct(input, handle = () => void 0) {
>construct : (input: Input, handle?: HookHandler | undefined) => State
>input : Input
>handle : (arg: Context) => void
>handle : import("tests/cases/conformance/jsdoc/declarations/hook").HookHandler
>() => void 0 : () => any
>void 0 : undefined
>0 : 0
@@ -129,9 +129,9 @@ Context.prototype = {
}
}
module.exports = Context;
>module.exports = Context : { (input: Input): Context; new (input: Input): Context; prototype: { construct(input: Input, handle?: (arg: Context) => void): State; }; }
>module.exports : { (input: Input): Context; new (input: Input): Context; prototype: { construct(input: Input, handle?: (arg: Context) => void): State; }; }
>module : { "\"tests/cases/conformance/jsdoc/declarations/context\"": { (input: Input): Context; new (input: Input): Context; prototype: { construct(input: Input, handle?: (arg: Context) => void): State; }; }; }
>exports : { (input: Input): Context; new (input: Input): Context; prototype: { construct(input: Input, handle?: (arg: Context) => void): State; }; }
>module.exports = Context : { (input: Input): Context; new (input: Input): Context; prototype: { construct(input: Input, handle?: import("tests/cases/conformance/jsdoc/declarations/hook").HookHandler): State; }; }
>module.exports : { (input: Input): Context; new (input: Input): Context; prototype: { construct(input: Input, handle?: import("tests/cases/conformance/jsdoc/declarations/hook").HookHandler): State; }; }
>module : { "\"tests/cases/conformance/jsdoc/declarations/context\"": { (input: Input): Context; new (input: Input): Context; prototype: { construct(input: Input, handle?: import("tests/cases/conformance/jsdoc/declarations/hook").HookHandler): State; }; }; }
>exports : { (input: Input): Context; new (input: Input): Context; prototype: { construct(input: Input, handle?: import("tests/cases/conformance/jsdoc/declarations/hook").HookHandler): State; }; }
>Context : typeof Context
@@ -68,7 +68,7 @@ export namespace myTypes {
/**
* - Prop 1.
*/
prop1: string | RegExp | (string | RegExp)[];
prop1: typeA;
/**
* - Prop 2.
*/
@@ -84,7 +84,7 @@ export namespace myTypes {
* @param {testFnTypes.input} input - Input.
* @returns {number|null} Result.
*/
export function testFn(input: boolean | Function | myTypes.typeB): number | null;
export function testFn(input: testFnTypes.input): number | null;
/**
* @namespace testFnTypes
* @global
@@ -70,6 +70,6 @@ function testFn(input) {
}
export {testFn, testFnTypes};
>testFn : (input: boolean | Function | myTypes.typeB) => number
>testFn : (input: testFnTypes.input) => number
>testFnTypes : { [x: string]: any; }
@@ -68,7 +68,7 @@ export namespace myTypes {
/**
* - Prop 1.
*/
prop1: string | RegExp | (string | RegExp)[];
prop1: typeA;
/**
* - Prop 2.
*/
@@ -84,16 +84,7 @@ export namespace myTypes {
* @param {testFnTypes.input} input - Input.
* @returns {number|null} Result.
*/
export function testFn(input: boolean | Function | {
/**
* - Prop 1.
*/
prop1: string | RegExp | (string | RegExp)[];
/**
* - Prop 2.
*/
prop2: string;
}): number | null;
export function testFn(input: testFnTypes.input): number | null;
/**
* @namespace testFnTypes
* @global
@@ -47,12 +47,12 @@ function testFn(input) {
}
module.exports = {testFn, testFnTypes};
>module.exports = {testFn, testFnTypes} : { testFn: (input: boolean | Function | { prop1: string | RegExp | (string | RegExp)[]; prop2: string; }) => number; testFnTypes: { [x: string]: any; }; }
>module.exports : { testFn: (input: boolean | Function | { prop1: string | RegExp | (string | RegExp)[]; prop2: string; }) => number; testFnTypes: { [x: string]: any; }; }
>module : { "\"tests/cases/conformance/jsdoc/declarations/file2\"": { testFn: (input: boolean | Function | { prop1: string | RegExp | (string | RegExp)[]; prop2: string; }) => number; testFnTypes: { [x: string]: any; }; }; }
>exports : { testFn: (input: boolean | Function | { prop1: string | RegExp | (string | RegExp)[]; prop2: string; }) => number; testFnTypes: { [x: string]: any; }; }
>{testFn, testFnTypes} : { testFn: (input: boolean | Function | { prop1: string | RegExp | (string | RegExp)[]; prop2: string; }) => number; testFnTypes: { [x: string]: any; }; }
>testFn : (input: boolean | Function | { prop1: string | RegExp | (string | RegExp)[]; prop2: string; }) => number
>module.exports = {testFn, testFnTypes} : { testFn: (input: testFnTypes.input) => number; testFnTypes: { [x: string]: any; }; }
>module.exports : { testFn: (input: testFnTypes.input) => number; testFnTypes: { [x: string]: any; }; }
>module : { "\"tests/cases/conformance/jsdoc/declarations/file2\"": { testFn: (input: testFnTypes.input) => number; testFnTypes: { [x: string]: any; }; }; }
>exports : { testFn: (input: testFnTypes.input) => number; testFnTypes: { [x: string]: any; }; }
>{testFn, testFnTypes} : { testFn: (input: testFnTypes.input) => number; testFnTypes: { [x: string]: any; }; }
>testFn : (input: testFnTypes.input) => number
>testFnTypes : { [x: string]: any; }
=== tests/cases/conformance/jsdoc/declarations/file.js ===
File diff suppressed because one or more lines are too long
@@ -53,14 +53,14 @@ class ExportedThing {
>"ok" : "ok"
}
module.exports = {
>module.exports = { doTheThing, ExportedThing,} : { doTheThing: (x: number) => number | { x: string; } | LocalThing | ExportedThing; ExportedThing: typeof ExportedThing; }
>module.exports : { doTheThing: (x: number) => number | { x: string; } | LocalThing | ExportedThing; ExportedThing: typeof ExportedThing; }
>module : { "\"tests/cases/conformance/jsdoc/declarations/mixed\"": { doTheThing: (x: number) => number | { x: string; } | LocalThing | ExportedThing; ExportedThing: typeof ExportedThing; }; }
>exports : { doTheThing: (x: number) => number | { x: string; } | LocalThing | ExportedThing; ExportedThing: typeof ExportedThing; }
>{ doTheThing, ExportedThing,} : { doTheThing: (x: number) => number | { x: string; } | LocalThing | ExportedThing; ExportedThing: typeof ExportedThing; }
>module.exports = { doTheThing, ExportedThing,} : { doTheThing: (x: number) => SomeType; ExportedThing: typeof ExportedThing; }
>module.exports : { doTheThing: (x: number) => SomeType; ExportedThing: typeof ExportedThing; }
>module : { "\"tests/cases/conformance/jsdoc/declarations/mixed\"": { doTheThing: (x: number) => SomeType; ExportedThing: typeof ExportedThing; }; }
>exports : { doTheThing: (x: number) => SomeType; ExportedThing: typeof ExportedThing; }
>{ doTheThing, ExportedThing,} : { doTheThing: (x: number) => SomeType; ExportedThing: typeof ExportedThing; }
doTheThing,
>doTheThing : (x: number) => number | { x: string; } | LocalThing | ExportedThing
>doTheThing : (x: number) => SomeType
ExportedThing,
>ExportedThing : typeof ExportedThing
@@ -48,9 +48,9 @@ class Wrap {
/** @type {import("./conn").Whatever} */
this.another = "";
>this.another = "" : ""
>this.another : string | number
>this.another : import("tests/cases/conformance/jsdoc/declarations/conn").Whatever
>this : this
>another : string | number
>another : import("tests/cases/conformance/jsdoc/declarations/conn").Whatever
>"" : ""
}
}
@@ -155,7 +155,7 @@ declare namespace MainThreadTasks {
export { TaskGroup, TaskNode, PriorTaskData };
}
type TaskGroup = {
id: "parseHTML" | "styleLayout";
id: import("./module.js").TaskGroupIds;
label: string;
traceEventNames: string[];
};
@@ -15,9 +15,9 @@ export const kSymbol = Symbol("my-symbol");
*/
export function b(value) {
>b : (value: import('./a').WithSymbol) => import('./a').WithSymbol
>value : { [kSymbol]: true; }
>value : import("tests/cases/conformance/jsdoc/declarations/a").WithSymbol
return value;
>value : { [kSymbol]: true; }
>value : import("tests/cases/conformance/jsdoc/declarations/a").WithSymbol
}
@@ -29,14 +29,14 @@ class Foo {
foo(x, y, alpha) {
>foo : (x: T, y: Id<T>, alpha: (t: T) => T) => T
>x : T
>y : (t: T) => T
>y : Id<T>
>alpha : (t: T) => T
return alpha(y(x))
>alpha(y(x)) : T
>alpha : (t: T) => T
>y(x) : T
>y : (t: T) => T
>y : Id<T>
>x : T
}
}
@@ -29,15 +29,15 @@ function Zet(t) {
* @param {Id<T>} id
*/
Zet.prototype.add = function(v, id) {
>Zet.prototype.add = function(v, id) { this.u = v || this.t return id(this.u)} : (v: T, id: (u: T) => T) => T
>Zet.prototype.add = function(v, id) { this.u = v || this.t return id(this.u)} : (v: T, id: Id<T>) => T
>Zet.prototype.add : any
>Zet.prototype : any
>Zet : typeof Zet
>prototype : any
>add : any
>function(v, id) { this.u = v || this.t return id(this.u)} : (v: T, id: (u: T) => T) => T
>function(v, id) { this.u = v || this.t return id(this.u)} : (v: T, id: Id<T>) => T
>v : T
>id : (u: T) => T
>id : Id<T>
this.u = v || this.t
>this.u = v || this.t : T
@@ -52,7 +52,7 @@ Zet.prototype.add = function(v, id) {
return id(this.u)
>id(this.u) : T
>id : (u: T) => T
>id : Id<T>
>this.u : T
>this : this
>u : T
@@ -4,7 +4,7 @@ No type information for this code./** @typedef {number} Third */
No type information for this code.=== tests/cases/conformance/jsdoc/index.js ===
/** @type {AnyEffect} */
let b;
>b : { [k: string]: any; }
>b : AnyEffect
/** @type {Third} */
let c;
@@ -0,0 +1,34 @@
tests/cases/conformance/types/typeRelationships/recursiveTypes/bug39372.js(25,7): error TS2322: Type '{}' is not assignable to type 'XMLObject<{ foo: string; }>'.
Type '{}' is missing the following properties from type '{ $A: { foo?: XMLObject<string>[]; }; $O: { foo?: { $$?: Record<string, string>; } & { $: string; }; }; $$?: Record<string, string>; }': $A, $O
==== tests/cases/conformance/types/typeRelationships/recursiveTypes/bug39372.js (1 errors) ====
/** @typedef {ReadonlyArray<Json>} JsonArray */
/** @typedef {{ readonly [key: string]: Json }} JsonRecord */
/** @typedef {boolean | number | string | null | JsonRecord | JsonArray | readonly []} Json */
/**
* @template T
* @typedef {{
$A: {
[K in keyof T]?: XMLObject<T[K]>[]
},
$O: {
[K in keyof T]?: {
$$?: Record<string, string>
} & (T[K] extends string ? {$:string} : XMLObject<T[K]>)
},
$$?: Record<string, string>,
} & {
[K in keyof T]?: (
T[K] extends string ? string
: XMLObject<T[K]>
)
}} XMLObject<T> */
/** @type {XMLObject<{foo:string}>} */
const p = {};
~
!!! error TS2322: Type '{}' is not assignable to type 'XMLObject<{ foo: string; }>'.
!!! error TS2322: Type '{}' is missing the following properties from type '{ $A: { foo?: XMLObject<string>[]; }; $O: { foo?: { $$?: Record<string, string>; } & { $: string; }; }; $$?: Record<string, string>; }': $A, $O
@@ -0,0 +1,97 @@
//// [bug39372.js]
/** @typedef {ReadonlyArray<Json>} JsonArray */
/** @typedef {{ readonly [key: string]: Json }} JsonRecord */
/** @typedef {boolean | number | string | null | JsonRecord | JsonArray | readonly []} Json */
/**
* @template T
* @typedef {{
$A: {
[K in keyof T]?: XMLObject<T[K]>[]
},
$O: {
[K in keyof T]?: {
$$?: Record<string, string>
} & (T[K] extends string ? {$:string} : XMLObject<T[K]>)
},
$$?: Record<string, string>,
} & {
[K in keyof T]?: (
T[K] extends string ? string
: XMLObject<T[K]>
)
}} XMLObject<T> */
/** @type {XMLObject<{foo:string}>} */
const p = {};
//// [bug39372.js]
/** @typedef {ReadonlyArray<Json>} JsonArray */
/** @typedef {{ readonly [key: string]: Json }} JsonRecord */
/** @typedef {boolean | number | string | null | JsonRecord | JsonArray | readonly []} Json */
/**
* @template T
* @typedef {{
$A: {
[K in keyof T]?: XMLObject<T[K]>[]
},
$O: {
[K in keyof T]?: {
$$?: Record<string, string>
} & (T[K] extends string ? {$:string} : XMLObject<T[K]>)
},
$$?: Record<string, string>,
} & {
[K in keyof T]?: (
T[K] extends string ? string
: XMLObject<T[K]>
)
}} XMLObject<T> */
/** @type {XMLObject<{foo:string}>} */
var p = {};
//// [bug39372.d.ts]
/** @typedef {ReadonlyArray<Json>} JsonArray */
/** @typedef {{ readonly [key: string]: Json }} JsonRecord */
/** @typedef {boolean | number | string | null | JsonRecord | JsonArray | readonly []} Json */
/**
* @template T
* @typedef {{
$A: {
[K in keyof T]?: XMLObject<T[K]>[]
},
$O: {
[K in keyof T]?: {
$$?: Record<string, string>
} & (T[K] extends string ? {$:string} : XMLObject<T[K]>)
},
$$?: Record<string, string>,
} & {
[K in keyof T]?: (
T[K] extends string ? string
: XMLObject<T[K]>
)
}} XMLObject<T> */
/** @type {XMLObject<{foo:string}>} */
declare const p: XMLObject<{
foo: string;
}>;
type JsonArray = readonly Json[];
type JsonRecord = {
readonly [key: string]: Json;
};
type Json = string | number | boolean | JsonRecord | JsonArray | readonly [];
/**
* <T>
*/
type XMLObject<T> = {
$A: { [K in keyof T]?: XMLObject<T[K]>[]; };
$O: { [K_1 in keyof T]?: {
$$?: Record<string, string>;
} & (T[K_1] extends string ? {
$: string;
} : XMLObject<T[K_1]>); };
$$?: Record<string, string>;
} & { [K_2 in keyof T]?: T[K_2] extends string ? string : XMLObject<T[K_2]>; };
@@ -0,0 +1,28 @@
=== tests/cases/conformance/types/typeRelationships/recursiveTypes/bug39372.js ===
/** @typedef {ReadonlyArray<Json>} JsonArray */
/** @typedef {{ readonly [key: string]: Json }} JsonRecord */
/** @typedef {boolean | number | string | null | JsonRecord | JsonArray | readonly []} Json */
/**
* @template T
* @typedef {{
$A: {
[K in keyof T]?: XMLObject<T[K]>[]
},
$O: {
[K in keyof T]?: {
$$?: Record<string, string>
} & (T[K] extends string ? {$:string} : XMLObject<T[K]>)
},
$$?: Record<string, string>,
} & {
[K in keyof T]?: (
T[K] extends string ? string
: XMLObject<T[K]>
)
}} XMLObject<T> */
/** @type {XMLObject<{foo:string}>} */
const p = {};
>p : Symbol(p, Decl(bug39372.js, 24, 5))
@@ -0,0 +1,29 @@
=== tests/cases/conformance/types/typeRelationships/recursiveTypes/bug39372.js ===
/** @typedef {ReadonlyArray<Json>} JsonArray */
/** @typedef {{ readonly [key: string]: Json }} JsonRecord */
/** @typedef {boolean | number | string | null | JsonRecord | JsonArray | readonly []} Json */
/**
* @template T
* @typedef {{
$A: {
[K in keyof T]?: XMLObject<T[K]>[]
},
$O: {
[K in keyof T]?: {
$$?: Record<string, string>
} & (T[K] extends string ? {$:string} : XMLObject<T[K]>)
},
$$?: Record<string, string>,
} & {
[K in keyof T]?: (
T[K] extends string ? string
: XMLObject<T[K]>
)
}} XMLObject<T> */
/** @type {XMLObject<{foo:string}>} */
const p = {};
>p : XMLObject<{ foo: string; }>
>{} : {}
@@ -67,7 +67,7 @@ exports.C = function() {
=== tests/cases/conformance/jsdoc/use.js ===
/** @type {import('./mod1').Both} */
var both1 = { type: 'a', x: 1 };
>both1 : { type: "a"; x: 1; } | { type: "b"; y: 1; }
>both1 : import("tests/cases/conformance/jsdoc/mod1").Both
>{ type: 'a', x: 1 } : { type: "a"; x: 1; }
>type : "a"
>'a' : "a"
@@ -76,13 +76,13 @@ var both1 = { type: 'a', x: 1 };
/** @type {import('./mod2').Both} */
var both2 = both1;
>both2 : { type: "a"; x: 1; } | { type: "b"; y: 1; }
>both1 : { type: "a"; x: 1; }
>both2 : import("tests/cases/conformance/jsdoc/mod2").Both
>both1 : import("tests/cases/conformance/jsdoc/mod1").A
/** @type {import('./mod3').Both} */
var both3 = both2;
>both3 : { type: "a"; x: 1; } | { type: "b"; y: 1; }
>both2 : { type: "a"; x: 1; }
>both3 : import("tests/cases/conformance/jsdoc/mod3").Both
>both2 : import("tests/cases/conformance/jsdoc/mod2").A
@@ -9,11 +9,11 @@
/** @type {Everything<{ a: number, b: 'hi', c: never }, undefined, { c: true, d: 1 }, number, string>} */
var tuvwx;
>tuvwx : { t: { a: number; b: "hi"; c: never; }; u: undefined; v: { c: true; d: 1; }; w: number; x: string; }
>tuvwx : Everything<{ a: number; b: "hi"; c: never; }, undefined, { c: true; d: 1; }, number, string>
/** @type {Everything<{ a: number }, undefined, { c: 1, d: 1 }, number, string>} */
var wrong;
>wrong : { t: { a: number; }; u: undefined; v: { c: 1; d: 1; }; w: number; x: string; }
>wrong : Everything<{ a: number; }, undefined, { c: 1; d: 1; }, number, string>
/** @type {Everything<{ a: number }>} */
var insufficient;
@@ -21,7 +21,7 @@ var insufficient;
=== tests/cases/conformance/jsdoc/test.ts ===
declare var actually: Everything<{ a: number }, undefined, { c: 1, d: 1 }, number, string>;
>actually : { t: { a: number; }; u: undefined; v: { c: 1; d: 1; }; w: number; x: string; }
>actually : Everything<{ a: number; }, undefined, { c: 1; d: 1; }, number, string>
>a : number
>c : 1
>d : 1
@@ -13,12 +13,12 @@
*/
function callIt(func, arg) {
>callIt : (func: Type1, arg: string) => boolean
>func : (arg0: string) => boolean
>func : Type1
>arg : string
return func(arg);
>func(arg) : boolean
>func : (arg0: string) => boolean
>func : Type1
>arg : string
}
@@ -38,18 +38,18 @@ function callIt(func, arg) {
*/
function check(obj) {
>check : (obj: Type2) => string | number
>obj : { num: number; str: string; boo: boolean; }
>obj : Type2
return obj.boo ? obj.num : obj.str;
>obj.boo ? obj.num : obj.str : string | number
>obj.boo : boolean
>obj : { num: number; str: string; boo: boolean; }
>obj : Type2
>boo : boolean
>obj.num : number
>obj : { num: number; str: string; boo: boolean; }
>obj : Type2
>num : number
>obj.str : string
>obj : { num: number; str: string; boo: boolean; }
>obj : Type2
>str : string
}
@@ -71,14 +71,14 @@ function check(obj) {
*/
function use1(func, bool, str, num) {
>use1 : (func: StringOrNumber1, bool: boolean, str: string, num: number) => string | number
>func : (arg0: boolean, arg1: string, arg2: number) => string | number
>func : StringOrNumber1
>bool : boolean
>str : string
>num : number
return func(bool, str, num)
>func(bool, str, num) : string | number
>func : (arg0: boolean, arg1: string, arg2: number) => string | number
>func : StringOrNumber1
>bool : boolean
>str : string
>num : number
@@ -103,14 +103,14 @@ function use1(func, bool, str, num) {
*/
function use2(func, bool, str, num) {
>use2 : (func: StringOrNumber2, bool: boolean, str: string, num: number) => string | number
>func : (arg0: boolean, arg1: string, arg2: number) => string | number
>func : StringOrNumber2
>bool : boolean
>str : string
>num : number
return func(bool, str, num)
>func(bool, str, num) : string | number
>func : (arg0: boolean, arg1: string, arg2: number) => string | number
>func : StringOrNumber2
>bool : boolean
>str : string
>num : number
@@ -135,18 +135,18 @@ function use2(func, bool, str, num) {
*/
function check5(obj) {
>check5 : (obj: Type5) => string | number
>obj : { num: number; str: string; boo: boolean; }
>obj : Type5
return obj.boo ? obj.num : obj.str;
>obj.boo ? obj.num : obj.str : string | number
>obj.boo : boolean
>obj : { num: number; str: string; boo: boolean; }
>obj : Type5
>boo : boolean
>obj.num : number
>obj : { num: number; str: string; boo: boolean; }
>obj : Type5
>num : number
>obj.str : string
>obj : { num: number; str: string; boo: boolean; }
>obj : Type5
>str : string
}
@@ -167,11 +167,11 @@ function check5(obj) {
*/
function check6(obj) {
>check6 : (obj: Type6) => any
>obj : { foo: any; bar: any; }
>obj : Type6
return obj.foo;
>obj.foo : any
>obj : { foo: any; bar: any; }
>obj : Type6
>foo : any
}
@@ -0,0 +1,29 @@
// @checkjs: true
// @outdir: out/
// @filename: bug39372.js
// @declaration: true
/** @typedef {ReadonlyArray<Json>} JsonArray */
/** @typedef {{ readonly [key: string]: Json }} JsonRecord */
/** @typedef {boolean | number | string | null | JsonRecord | JsonArray | readonly []} Json */
/**
* @template T
* @typedef {{
$A: {
[K in keyof T]?: XMLObject<T[K]>[]
},
$O: {
[K in keyof T]?: {
$$?: Record<string, string>
} & (T[K] extends string ? {$:string} : XMLObject<T[K]>)
},
$$?: Record<string, string>,
} & {
[K in keyof T]?: (
T[K] extends string ? string
: XMLObject<T[K]>
)
}} XMLObject<T> */
/** @type {XMLObject<{foo:string}>} */
const p = {};