diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5ffe3c1e55373..5a87354dea5f2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4713,6 +4713,10 @@ namespace ts { // function/class/{} assignments are fresh declarations, not property assignments, so only add prototype assignments const specialDeclaration = getAssignedJavascriptInitializer(symbol.valueDeclaration); if (specialDeclaration) { + const tag = getJSDocTypeTag(specialDeclaration); + if (tag && tag.typeExpression) { + return getTypeFromTypeNode(tag.typeExpression); + } return getWidenedLiteralType(checkExpressionCached(specialDeclaration)); } const types: Type[] = []; @@ -5080,7 +5084,7 @@ namespace ts { } function getJSInitializerType(decl: Node, symbol: Symbol, init: Expression | undefined): Type | undefined { - if (init && isInJavaScriptFile(init) && isObjectLiteralExpression(init)) { + if (init && isInJavaScriptFile(init) && isObjectLiteralExpression(init) && init.properties.length === 0) { const exports = createSymbolTable(); while (isBinaryExpression(decl) || isPropertyAccessExpression(decl)) { const s = getSymbolOfNode(decl); diff --git a/tests/baselines/reference/chainedPrototypeAssignment.types b/tests/baselines/reference/chainedPrototypeAssignment.types index f0d9cc972ef0f..a893ae63022c6 100644 --- a/tests/baselines/reference/chainedPrototypeAssignment.types +++ b/tests/baselines/reference/chainedPrototypeAssignment.types @@ -86,9 +86,9 @@ A.prototype = B.prototype = { >A : typeof A >prototype : { [x: string]: any; m(n: number): number; } >B.prototype = { /** @param {number} n */ m(n) { return n + 1 }} : { [x: string]: any; m(n: number): number; } ->B.prototype : { [x: string]: any; } +>B.prototype : { [x: string]: any; m(n: number): number; } >B : typeof B ->prototype : { [x: string]: any; } +>prototype : { [x: string]: any; m(n: number): number; } >{ /** @param {number} n */ m(n) { return n + 1 }} : { [x: string]: any; m(n: number): number; } /** @param {number} n */ diff --git a/tests/baselines/reference/contextualTypedSpecialAssignment.errors.txt b/tests/baselines/reference/contextualTypedSpecialAssignment.errors.txt index e918ff187aeb6..c5851c4614711 100644 --- a/tests/baselines/reference/contextualTypedSpecialAssignment.errors.txt +++ b/tests/baselines/reference/contextualTypedSpecialAssignment.errors.txt @@ -1,9 +1,8 @@ tests/cases/conformance/salsa/mod.js(5,7): error TS7006: Parameter 'n' implicitly has an 'any' type. tests/cases/conformance/salsa/test.js(52,7): error TS7006: Parameter 'n' implicitly has an 'any' type. -tests/cases/conformance/salsa/test.js(70,7): error TS7006: Parameter 'n' implicitly has an 'any' type. -==== tests/cases/conformance/salsa/test.js (2 errors) ==== +==== tests/cases/conformance/salsa/test.js (1 errors) ==== /** @typedef {{ status: 'done' m(n: number): void @@ -76,13 +75,11 @@ tests/cases/conformance/salsa/test.js(70,7): error TS7006: Parameter 'n' implici F.prototype = { status: "done", m(n) { } - ~ -!!! error TS7006: Parameter 'n' implicitly has an 'any' type. } ==== tests/cases/conformance/salsa/mod.js (1 errors) ==== // module.exports assignment - /** @type {{ status: 'done' }} */ + /** @type {{ status: 'done', m(n: number): void }} */ module.exports = { status: "done", m(n) { } diff --git a/tests/baselines/reference/contextualTypedSpecialAssignment.symbols b/tests/baselines/reference/contextualTypedSpecialAssignment.symbols index dac01d09bcc5e..2a8b1650ae7bc 100644 --- a/tests/baselines/reference/contextualTypedSpecialAssignment.symbols +++ b/tests/baselines/reference/contextualTypedSpecialAssignment.symbols @@ -158,7 +158,7 @@ F.prototype = { === tests/cases/conformance/salsa/mod.js === // module.exports assignment -/** @type {{ status: 'done' }} */ +/** @type {{ status: 'done', m(n: number): void }} */ module.exports = { >module : Symbol(export=, Decl(mod.js, 0, 0)) >exports : Symbol(export=, Decl(mod.js, 0, 0)) diff --git a/tests/baselines/reference/contextualTypedSpecialAssignment.types b/tests/baselines/reference/contextualTypedSpecialAssignment.types index 04f32e7a6feb9..5bd81e65283e4 100644 --- a/tests/baselines/reference/contextualTypedSpecialAssignment.types +++ b/tests/baselines/reference/contextualTypedSpecialAssignment.types @@ -172,24 +172,24 @@ function F() { } /** @type {DoneStatus} */ F.prototype = { ->F.prototype = { status: "done", m(n) { }} : { status: string; m(n: any): void; } ->F.prototype : { [x: string]: any; } +>F.prototype = { status: "done", m(n) { }} : { status: "done"; m(n: number): void; } +>F.prototype : { status: "done"; m(n: number): void; } >F : typeof F ->prototype : { [x: string]: any; } ->{ status: "done", m(n) { }} : { status: string; m(n: any): void; } +>prototype : { status: "done"; m(n: number): void; } +>{ status: "done", m(n) { }} : { status: "done"; m(n: number): void; } status: "done", ->status : string +>status : "done" >"done" : "done" m(n) { } ->m : (n: any) => void ->n : any +>m : (n: number) => void +>n : number } === tests/cases/conformance/salsa/mod.js === // module.exports assignment -/** @type {{ status: 'done' }} */ +/** @type {{ status: 'done', m(n: number): void }} */ module.exports = { >module.exports = { status: "done", m(n) { }} : { status: string; m(n: any): void; } >module.exports : any diff --git a/tests/baselines/reference/typeFromPropertyAssignment11.types b/tests/baselines/reference/typeFromPropertyAssignment11.types index 87a709d7cf3a4..8c90e824f23c5 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment11.types +++ b/tests/baselines/reference/typeFromPropertyAssignment11.types @@ -5,9 +5,9 @@ var Inner = function() {} Inner.prototype = { >Inner.prototype = { m() { }, i: 1} : { [x: string]: any; m(): void; i: number; } ->Inner.prototype : { [x: string]: any; } +>Inner.prototype : { [x: string]: any; m(): void; i: number; } >Inner : typeof Inner ->prototype : { [x: string]: any; } +>prototype : { [x: string]: any; m(): void; i: number; } >{ m() { }, i: 1} : { [x: string]: any; m(): void; i: number; } m() { }, @@ -21,18 +21,18 @@ Inner.prototype = { Inner.prototype.j = 2 >Inner.prototype.j = 2 : 2 >Inner.prototype.j : any ->Inner.prototype : { [x: string]: any; } +>Inner.prototype : { [x: string]: any; m(): void; i: number; } >Inner : typeof Inner ->prototype : { [x: string]: any; } +>prototype : { [x: string]: any; m(): void; i: number; } >j : any >2 : 2 /** @type {string} */ Inner.prototype.k; >Inner.prototype.k : any ->Inner.prototype : { [x: string]: any; } +>Inner.prototype : { [x: string]: any; m(): void; i: number; } >Inner : typeof Inner ->prototype : { [x: string]: any; } +>prototype : { [x: string]: any; m(): void; i: number; } >k : any var inner = new Inner() diff --git a/tests/baselines/reference/typeFromPropertyAssignment13.types b/tests/baselines/reference/typeFromPropertyAssignment13.types index 5b97d2986f57c..f85325a60a22c 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment13.types +++ b/tests/baselines/reference/typeFromPropertyAssignment13.types @@ -12,11 +12,11 @@ Outer.Inner = function() {} Outer.Inner.prototype = { >Outer.Inner.prototype = { m() { }, i: 1} : { [x: string]: any; m(): void; i: number; } ->Outer.Inner.prototype : { [x: string]: any; } +>Outer.Inner.prototype : { [x: string]: any; m(): void; i: number; } >Outer.Inner : typeof Inner >Outer : typeof Outer >Inner : typeof Inner ->prototype : { [x: string]: any; } +>prototype : { [x: string]: any; m(): void; i: number; } >{ m() { }, i: 1} : { [x: string]: any; m(): void; i: number; } m() { }, @@ -30,22 +30,22 @@ Outer.Inner.prototype = { Outer.Inner.prototype.j = 2 >Outer.Inner.prototype.j = 2 : 2 >Outer.Inner.prototype.j : any ->Outer.Inner.prototype : { [x: string]: any; } +>Outer.Inner.prototype : { [x: string]: any; m(): void; i: number; } >Outer.Inner : typeof Inner >Outer : typeof Outer >Inner : typeof Inner ->prototype : { [x: string]: any; } +>prototype : { [x: string]: any; m(): void; i: number; } >j : any >2 : 2 /** @type {string} */ Outer.Inner.prototype.k; >Outer.Inner.prototype.k : any ->Outer.Inner.prototype : { [x: string]: any; } +>Outer.Inner.prototype : { [x: string]: any; m(): void; i: number; } >Outer.Inner : typeof Inner >Outer : typeof Outer >Inner : typeof Inner ->prototype : { [x: string]: any; } +>prototype : { [x: string]: any; m(): void; i: number; } >k : any var inner = new Outer.Inner() diff --git a/tests/baselines/reference/typeFromPropertyAssignment14.types b/tests/baselines/reference/typeFromPropertyAssignment14.types index 60d63c489d6b3..a20a5a15fc3c6 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment14.types +++ b/tests/baselines/reference/typeFromPropertyAssignment14.types @@ -5,19 +5,19 @@ var Outer = {}; === tests/cases/conformance/salsa/work.js === Outer.Inner = function () {} ->Outer.Inner = function () {} : { (): void; prototype: { [x: string]: any; }; } ->Outer.Inner : { (): void; prototype: { [x: string]: any; }; } +>Outer.Inner = function () {} : { (): void; prototype: { [x: string]: any; x: number; m(): void; }; } +>Outer.Inner : { (): void; prototype: { [x: string]: any; x: number; m(): void; }; } >Outer : typeof Outer ->Inner : { (): void; prototype: { [x: string]: any; }; } ->function () {} : { (): void; prototype: { [x: string]: any; }; } +>Inner : { (): void; prototype: { [x: string]: any; x: number; m(): void; }; } +>function () {} : { (): void; prototype: { [x: string]: any; x: number; m(): void; }; } Outer.Inner.prototype = { >Outer.Inner.prototype = { x: 1, m() { }} : { [x: string]: any; x: number; m(): void; } ->Outer.Inner.prototype : { [x: string]: any; } ->Outer.Inner : { (): void; prototype: { [x: string]: any; }; } +>Outer.Inner.prototype : { [x: string]: any; x: number; m(): void; } +>Outer.Inner : { (): void; prototype: { [x: string]: any; x: number; m(): void; }; } >Outer : typeof Outer ->Inner : { (): void; prototype: { [x: string]: any; }; } ->prototype : { [x: string]: any; } +>Inner : { (): void; prototype: { [x: string]: any; x: number; m(): void; }; } +>prototype : { [x: string]: any; x: number; m(): void; } >{ x: 1, m() { }} : { [x: string]: any; x: number; m(): void; } x: 1, @@ -47,9 +47,9 @@ inner.m() var inno = new Outer.Inner() >inno : { [x: string]: any; x: number; m(): void; } >new Outer.Inner() : { [x: string]: any; x: number; m(): void; } ->Outer.Inner : { (): void; prototype: { [x: string]: any; }; } +>Outer.Inner : { (): void; prototype: { [x: string]: any; x: number; m(): void; }; } >Outer : typeof Outer ->Inner : { (): void; prototype: { [x: string]: any; }; } +>Inner : { (): void; prototype: { [x: string]: any; x: number; m(): void; }; } inno.x >inno.x : number diff --git a/tests/baselines/reference/typeFromPropertyAssignment16.types b/tests/baselines/reference/typeFromPropertyAssignment16.types index d67d6ccca3763..ce0ae3ae16e23 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment16.types +++ b/tests/baselines/reference/typeFromPropertyAssignment16.types @@ -4,19 +4,19 @@ var Outer = {}; >{} : { [x: string]: any; } Outer.Inner = function () {} ->Outer.Inner = function () {} : { (): void; prototype: { [x: string]: any; }; } ->Outer.Inner : { (): void; prototype: { [x: string]: any; }; } +>Outer.Inner = function () {} : { (): void; prototype: { [x: string]: any; x: number; m(): void; }; } +>Outer.Inner : { (): void; prototype: { [x: string]: any; x: number; m(): void; }; } >Outer : typeof Outer ->Inner : { (): void; prototype: { [x: string]: any; }; } ->function () {} : { (): void; prototype: { [x: string]: any; }; } +>Inner : { (): void; prototype: { [x: string]: any; x: number; m(): void; }; } +>function () {} : { (): void; prototype: { [x: string]: any; x: number; m(): void; }; } Outer.Inner.prototype = { >Outer.Inner.prototype = { x: 1, m() { }} : { [x: string]: any; x: number; m(): void; } ->Outer.Inner.prototype : { [x: string]: any; } ->Outer.Inner : { (): void; prototype: { [x: string]: any; }; } +>Outer.Inner.prototype : { [x: string]: any; x: number; m(): void; } +>Outer.Inner : { (): void; prototype: { [x: string]: any; x: number; m(): void; }; } >Outer : typeof Outer ->Inner : { (): void; prototype: { [x: string]: any; }; } ->prototype : { [x: string]: any; } +>Inner : { (): void; prototype: { [x: string]: any; x: number; m(): void; }; } +>prototype : { [x: string]: any; x: number; m(): void; } >{ x: 1, m() { }} : { [x: string]: any; x: number; m(): void; } x: 1, @@ -45,9 +45,9 @@ inner.m() var inno = new Outer.Inner() >inno : { [x: string]: any; x: number; m(): void; } >new Outer.Inner() : { [x: string]: any; x: number; m(): void; } ->Outer.Inner : { (): void; prototype: { [x: string]: any; }; } +>Outer.Inner : { (): void; prototype: { [x: string]: any; x: number; m(): void; }; } >Outer : typeof Outer ->Inner : { (): void; prototype: { [x: string]: any; }; } +>Inner : { (): void; prototype: { [x: string]: any; x: number; m(): void; }; } inno.x >inno.x : number diff --git a/tests/baselines/reference/typeFromPropertyAssignment27.types b/tests/baselines/reference/typeFromPropertyAssignment27.types index 222bd04e74d14..dcaefe7a95575 100644 --- a/tests/baselines/reference/typeFromPropertyAssignment27.types +++ b/tests/baselines/reference/typeFromPropertyAssignment27.types @@ -10,9 +10,9 @@ function C() { this.p = 1; } C.prototype = { q: 2 }; >C.prototype = { q: 2 } : { [x: string]: any; q: number; } ->C.prototype : { [x: string]: any; } +>C.prototype : { [x: string]: any; q: number; } >C : typeof C ->prototype : { [x: string]: any; } +>prototype : { [x: string]: any; q: number; } >{ q: 2 } : { [x: string]: any; q: number; } >q : number >2 : 2 diff --git a/tests/cases/conformance/salsa/contextualTypedSpecialAssignment.ts b/tests/cases/conformance/salsa/contextualTypedSpecialAssignment.ts index 4b67e8b9687fc..e4a2b56970c1b 100644 --- a/tests/cases/conformance/salsa/contextualTypedSpecialAssignment.ts +++ b/tests/cases/conformance/salsa/contextualTypedSpecialAssignment.ts @@ -77,7 +77,7 @@ F.prototype = { // @Filename: mod.js // module.exports assignment -/** @type {{ status: 'done' }} */ +/** @type {{ status: 'done', m(n: number): void }} */ module.exports = { status: "done", m(n) { }