diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index da1af15dfa458..57de68ab02b39 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2140,7 +2140,7 @@ namespace ts { } } - function getJSSpecialAssignmentLocation(node: TypeReferenceNode): Declaration | undefined { + function getJSSpecialAssignmentLocation(node: TypeReferenceNode): Node | undefined { const typeAlias = findAncestor(node, node => !(isJSDocNode(node) || node.flags & NodeFlags.JSDoc) ? "quit" : isJSDocTypeAlias(node)); if (typeAlias) { return; @@ -2149,8 +2149,20 @@ namespace ts { if (isExpressionStatement(host) && isBinaryExpression(host.expression) && getSpecialPropertyAssignmentKind(host.expression) === SpecialPropertyAssignmentKind.PrototypeProperty) { + // X.prototype.m = /** @param {K} p */ function () { } <-- look for K on X's declaration const symbol = getSymbolOfNode(host.expression.left); - return symbol && symbol.parent!.valueDeclaration; + if (symbol) { + return getDeclarationOfJSPrototypeContainer(symbol); + } + } + if ((isObjectLiteralMethod(host) || isPropertyAssignment(host)) && + isBinaryExpression(host.parent.parent) && + getSpecialPropertyAssignmentKind(host.parent.parent) === SpecialPropertyAssignmentKind.Prototype) { + // X.prototype = { /** @param {K} p */m() { } } <-- look for K on X's declaration + const symbol = getSymbolOfNode(host.parent.parent.left); + if (symbol) { + return getDeclarationOfJSPrototypeContainer(symbol); + } } const sig = getHostSignatureFromJSDocHost(host); if (sig) { @@ -2159,6 +2171,14 @@ namespace ts { } } + function getDeclarationOfJSPrototypeContainer(symbol: Symbol) { + const decl = symbol.parent!.valueDeclaration; + const initializer = isAssignmentDeclaration(decl) ? getAssignedJavascriptInitializer(decl) : + hasOnlyExpressionInitializer(decl) ? getDeclaredJavascriptInitializer(decl) : + undefined; + return initializer || decl; + } + function resolveExternalModuleName(location: Node, moduleReferenceExpression: Expression): Symbol | undefined { return resolveExternalModuleNameWorker(location, moduleReferenceExpression, Diagnostics.Cannot_find_module_0); } diff --git a/tests/baselines/reference/jsdocTemplateTag4.symbols b/tests/baselines/reference/jsdocTemplateTag4.symbols new file mode 100644 index 0000000000000..02ce7221fc2be --- /dev/null +++ b/tests/baselines/reference/jsdocTemplateTag4.symbols @@ -0,0 +1,113 @@ +=== tests/cases/conformance/jsdoc/a.js === +/** + * Should work for function declarations + * @constructor + * @template {string} K + * @template V + */ +function Multimap() { +>Multimap : Symbol(Multimap, Decl(a.js, 0, 0)) + + /** @type {Object} TODO: Remove the prototype from the fresh object */ + this._map = {}; +>this._map : Symbol(Multimap._map, Decl(a.js, 6, 21)) +>this : Symbol(Multimap, Decl(a.js, 0, 0)) +>_map : Symbol(Multimap._map, Decl(a.js, 6, 21)) + +}; + +/** + * @param {K} key the key ok + * @returns {V} the value ok + */ +Multimap.prototype.get = function (key) { +>Multimap.prototype : Symbol(Multimap.get, Decl(a.js, 9, 2)) +>Multimap : Symbol(Multimap, Decl(a.js, 0, 0)) +>prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --)) +>get : Symbol(Multimap.get, Decl(a.js, 9, 2)) +>key : Symbol(key, Decl(a.js, 15, 35)) + + return this._map[key + '']; +>this._map : Symbol(Multimap._map, Decl(a.js, 6, 21)) +>this : Symbol(Multimap, Decl(a.js, 0, 0)) +>_map : Symbol(Multimap._map, Decl(a.js, 6, 21)) +>key : Symbol(key, Decl(a.js, 15, 35)) +} + +/** + * Should work for initialisers too + * @constructor + * @template {string} K + * @template V + */ +var Multimap2 = function() { +>Multimap2 : Symbol(Multimap2, Decl(a.js, 25, 3)) + + /** @type {Object} TODO: Remove the prototype from the fresh object */ + this._map = {}; +>this._map : Symbol(Multimap2._map, Decl(a.js, 25, 28)) +>this : Symbol(Multimap2, Decl(a.js, 25, 15)) +>_map : Symbol(Multimap2._map, Decl(a.js, 25, 28)) + +}; + +/** + * @param {K} key the key ok + * @returns {V} the value ok + */ +Multimap2.prototype.get = function (key) { +>Multimap2.prototype : Symbol(Multimap2.get, Decl(a.js, 28, 2)) +>Multimap2 : Symbol(Multimap2, Decl(a.js, 25, 3)) +>prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --)) +>get : Symbol(Multimap2.get, Decl(a.js, 28, 2)) +>key : Symbol(key, Decl(a.js, 34, 36)) + + return this._map[key + '']; +>this._map : Symbol(Multimap2._map, Decl(a.js, 25, 28)) +>this : Symbol(Multimap2, Decl(a.js, 25, 15)) +>_map : Symbol(Multimap2._map, Decl(a.js, 25, 28)) +>key : Symbol(key, Decl(a.js, 34, 36)) +} + +var Ns = {}; +>Ns : Symbol(Ns, Decl(a.js, 38, 3), Decl(a.js, 38, 12)) + +/** + * Should work for expando-namespaced initialisers too + * @constructor + * @template {string} K + * @template V + */ +Ns.Multimap3 = function() { +>Ns.Multimap3 : Symbol(Ns.Multimap3, Decl(a.js, 38, 12)) +>Ns : Symbol(Ns, Decl(a.js, 38, 3), Decl(a.js, 38, 12)) +>Multimap3 : Symbol(Ns.Multimap3, Decl(a.js, 38, 12)) + + /** @type {Object} TODO: Remove the prototype from the fresh object */ + this._map = {}; +>this._map : Symbol(Multimap3._map, Decl(a.js, 45, 27)) +>this : Symbol(Multimap3, Decl(a.js, 45, 14)) +>_map : Symbol(Multimap3._map, Decl(a.js, 45, 27)) + +}; + +/** + * @param {K} key the key ok + * @returns {V} the value ok + */ +Ns.Multimap3.prototype.get = function (key) { +>Ns.Multimap3.prototype : Symbol(Ns.Multimap3.get, Decl(a.js, 48, 2)) +>Ns.Multimap3 : Symbol(Ns.Multimap3, Decl(a.js, 38, 12)) +>Ns : Symbol(Ns, Decl(a.js, 38, 3), Decl(a.js, 38, 12)) +>Multimap3 : Symbol(Ns.Multimap3, Decl(a.js, 38, 12)) +>prototype : Symbol(Function.prototype, Decl(lib.es5.d.ts, --, --)) +>get : Symbol(Ns.Multimap3.get, Decl(a.js, 48, 2)) +>key : Symbol(key, Decl(a.js, 54, 39)) + + return this._map[key + '']; +>this._map : Symbol(Multimap3._map, Decl(a.js, 45, 27)) +>this : Symbol(Multimap3, Decl(a.js, 45, 14)) +>_map : Symbol(Multimap3._map, Decl(a.js, 45, 27)) +>key : Symbol(key, Decl(a.js, 54, 39)) +} + diff --git a/tests/baselines/reference/jsdocTemplateTag4.types b/tests/baselines/reference/jsdocTemplateTag4.types new file mode 100644 index 0000000000000..6df18d4b98a35 --- /dev/null +++ b/tests/baselines/reference/jsdocTemplateTag4.types @@ -0,0 +1,141 @@ +=== tests/cases/conformance/jsdoc/a.js === +/** + * Should work for function declarations + * @constructor + * @template {string} K + * @template V + */ +function Multimap() { +>Multimap : typeof Multimap + + /** @type {Object} TODO: Remove the prototype from the fresh object */ + this._map = {}; +>this._map = {} : {} +>this._map : { [x: string]: V; } +>this : Multimap +>_map : { [x: string]: V; } +>{} : {} + +}; + +/** + * @param {K} key the key ok + * @returns {V} the value ok + */ +Multimap.prototype.get = function (key) { +>Multimap.prototype.get = function (key) { return this._map[key + ''];} : (key: K) => V +>Multimap.prototype.get : any +>Multimap.prototype : any +>Multimap : typeof Multimap +>prototype : any +>get : any +>function (key) { return this._map[key + ''];} : (key: K) => V +>key : K + + return this._map[key + '']; +>this._map[key + ''] : V +>this._map : { [x: string]: V; } +>this : Multimap +>_map : { [x: string]: V; } +>key + '' : string +>key : K +>'' : "" +} + +/** + * Should work for initialisers too + * @constructor + * @template {string} K + * @template V + */ +var Multimap2 = function() { +>Multimap2 : typeof Multimap2 +>function() { /** @type {Object} TODO: Remove the prototype from the fresh object */ this._map = {};} : typeof Multimap2 + + /** @type {Object} TODO: Remove the prototype from the fresh object */ + this._map = {}; +>this._map = {} : {} +>this._map : { [x: string]: V; } +>this : Multimap2 +>_map : { [x: string]: V; } +>{} : {} + +}; + +/** + * @param {K} key the key ok + * @returns {V} the value ok + */ +Multimap2.prototype.get = function (key) { +>Multimap2.prototype.get = function (key) { return this._map[key + ''];} : (key: K) => V +>Multimap2.prototype.get : any +>Multimap2.prototype : any +>Multimap2 : typeof Multimap2 +>prototype : any +>get : any +>function (key) { return this._map[key + ''];} : (key: K) => V +>key : K + + return this._map[key + '']; +>this._map[key + ''] : V +>this._map : { [x: string]: V; } +>this : Multimap2 +>_map : { [x: string]: V; } +>key + '' : string +>key : K +>'' : "" +} + +var Ns = {}; +>Ns : typeof Ns +>{} : {} + +/** + * Should work for expando-namespaced initialisers too + * @constructor + * @template {string} K + * @template V + */ +Ns.Multimap3 = function() { +>Ns.Multimap3 = function() { /** @type {Object} TODO: Remove the prototype from the fresh object */ this._map = {};} : typeof Multimap3 +>Ns.Multimap3 : typeof Multimap3 +>Ns : typeof Ns +>Multimap3 : typeof Multimap3 +>function() { /** @type {Object} TODO: Remove the prototype from the fresh object */ this._map = {};} : typeof Multimap3 + + /** @type {Object} TODO: Remove the prototype from the fresh object */ + this._map = {}; +>this._map = {} : {} +>this._map : { [x: string]: V; } +>this : Multimap3 +>_map : { [x: string]: V; } +>{} : {} + +}; + +/** + * @param {K} key the key ok + * @returns {V} the value ok + */ +Ns.Multimap3.prototype.get = function (key) { +>Ns.Multimap3.prototype.get = function (key) { return this._map[key + ''];} : (key: K) => V +>Ns.Multimap3.prototype.get : any +>Ns.Multimap3.prototype : any +>Ns.Multimap3 : typeof Multimap3 +>Ns : typeof Ns +>Multimap3 : typeof Multimap3 +>prototype : any +>get : any +>function (key) { return this._map[key + ''];} : (key: K) => V +>key : K + + return this._map[key + '']; +>this._map[key + ''] : V +>this._map : { [x: string]: V; } +>this : Multimap3 +>_map : { [x: string]: V; } +>key + '' : string +>key : K +>'' : "" +} + diff --git a/tests/baselines/reference/jsdocTemplateTag5.errors.txt b/tests/baselines/reference/jsdocTemplateTag5.errors.txt new file mode 100644 index 0000000000000..e24cd0926b6d8 --- /dev/null +++ b/tests/baselines/reference/jsdocTemplateTag5.errors.txt @@ -0,0 +1,77 @@ +tests/cases/conformance/jsdoc/a.js(18,21): error TS2339: Property '_map' does not exist on type '{ get(key: K): V; }'. +tests/cases/conformance/jsdoc/a.js(39,21): error TS2339: Property '_map' does not exist on type '{ get: (key: K) => V; }'. +tests/cases/conformance/jsdoc/a.js(61,21): error TS2339: Property '_map' does not exist on type '{ get(key: K): V; }'. + + +==== tests/cases/conformance/jsdoc/a.js (3 errors) ==== + /** + * Should work for function declarations + * @constructor + * @template {string} K + * @template V + */ + function Multimap() { + /** @type {Object} TODO: Remove the prototype from the fresh object */ + this._map = {}; + }; + + Multimap.prototype = { + /** + * @param {K} key the key ok + * @returns {V} the value ok + */ + get(key) { + return this._map[key + '']; + ~~~~ +!!! error TS2339: Property '_map' does not exist on type '{ get(key: K): V; }'. + } + } + + /** + * Should work for initialisers too + * @constructor + * @template {string} K + * @template V + */ + var Multimap2 = function() { + /** @type {Object} TODO: Remove the prototype from the fresh object */ + this._map = {}; + }; + + Multimap2.prototype = { + /** + * @param {K} key the key ok + * @returns {V} the value ok + */ + get: function(key) { + return this._map[key + '']; + ~~~~ +!!! error TS2339: Property '_map' does not exist on type '{ get: (key: K) => V; }'. + } + } + + var Ns = {}; + /** + * Should work for expando-namespaced initialisers too + * @constructor + * @template {string} K + * @template V + */ + Ns.Multimap3 = function() { + /** @type {Object} TODO: Remove the prototype from the fresh object */ + this._map = {}; + }; + + Ns.Multimap3.prototype = { + /** + * @param {K} key the key ok + * @returns {V} the value ok + */ + get(key) { + return this._map[key + '']; + ~~~~ +!!! error TS2339: Property '_map' does not exist on type '{ get(key: K): V; }'. + } + } + + \ No newline at end of file diff --git a/tests/baselines/reference/jsdocTemplateTag5.symbols b/tests/baselines/reference/jsdocTemplateTag5.symbols new file mode 100644 index 0000000000000..249e92ab257f6 --- /dev/null +++ b/tests/baselines/reference/jsdocTemplateTag5.symbols @@ -0,0 +1,114 @@ +=== tests/cases/conformance/jsdoc/a.js === +/** + * Should work for function declarations + * @constructor + * @template {string} K + * @template V + */ +function Multimap() { +>Multimap : Symbol(Multimap, Decl(a.js, 0, 0), Decl(a.js, 9, 2)) + + /** @type {Object} TODO: Remove the prototype from the fresh object */ + this._map = {}; +>this._map : Symbol(Multimap._map, Decl(a.js, 6, 21)) +>_map : Symbol(Multimap._map, Decl(a.js, 6, 21)) + +}; + +Multimap.prototype = { +>Multimap.prototype : Symbol(Multimap.prototype, Decl(a.js, 9, 2)) +>Multimap : Symbol(Multimap, Decl(a.js, 0, 0), Decl(a.js, 9, 2)) +>prototype : Symbol(Multimap.prototype, Decl(a.js, 9, 2)) + + /** + * @param {K} key the key ok + * @returns {V} the value ok + */ + get(key) { +>get : Symbol(get, Decl(a.js, 11, 22)) +>key : Symbol(key, Decl(a.js, 16, 8)) + + return this._map[key + '']; +>this : Symbol(__object, Decl(a.js, 11, 20)) +>key : Symbol(key, Decl(a.js, 16, 8)) + } +} + +/** + * Should work for initialisers too + * @constructor + * @template {string} K + * @template V + */ +var Multimap2 = function() { +>Multimap2 : Symbol(Multimap2, Decl(a.js, 27, 3), Decl(a.js, 30, 2)) + + /** @type {Object} TODO: Remove the prototype from the fresh object */ + this._map = {}; +>this._map : Symbol(Multimap2._map, Decl(a.js, 27, 28)) +>_map : Symbol(Multimap2._map, Decl(a.js, 27, 28)) + +}; + +Multimap2.prototype = { +>Multimap2.prototype : Symbol(Multimap2.prototype, Decl(a.js, 30, 2)) +>Multimap2 : Symbol(Multimap2, Decl(a.js, 27, 3), Decl(a.js, 30, 2)) +>prototype : Symbol(Multimap2.prototype, Decl(a.js, 30, 2)) + + /** + * @param {K} key the key ok + * @returns {V} the value ok + */ + get: function(key) { +>get : Symbol(get, Decl(a.js, 32, 23)) +>key : Symbol(key, Decl(a.js, 37, 18)) + + return this._map[key + '']; +>this : Symbol(__object, Decl(a.js, 32, 21)) +>key : Symbol(key, Decl(a.js, 37, 18)) + } +} + +var Ns = {}; +>Ns : Symbol(Ns, Decl(a.js, 42, 3), Decl(a.js, 42, 12), Decl(a.js, 52, 2)) + +/** + * Should work for expando-namespaced initialisers too + * @constructor + * @template {string} K + * @template V + */ +Ns.Multimap3 = function() { +>Ns.Multimap3 : Symbol(Ns.Multimap3, Decl(a.js, 42, 12), Decl(a.js, 54, 3)) +>Ns : Symbol(Ns, Decl(a.js, 42, 3), Decl(a.js, 42, 12), Decl(a.js, 52, 2)) +>Multimap3 : Symbol(Ns.Multimap3, Decl(a.js, 42, 12), Decl(a.js, 54, 3)) + + /** @type {Object} TODO: Remove the prototype from the fresh object */ + this._map = {}; +>this._map : Symbol(Multimap3._map, Decl(a.js, 49, 27)) +>_map : Symbol(Multimap3._map, Decl(a.js, 49, 27)) + +}; + +Ns.Multimap3.prototype = { +>Ns.Multimap3.prototype : Symbol(Ns.Multimap3.prototype, Decl(a.js, 52, 2)) +>Ns.Multimap3 : Symbol(Ns.Multimap3, Decl(a.js, 42, 12), Decl(a.js, 54, 3)) +>Ns : Symbol(Ns, Decl(a.js, 42, 3), Decl(a.js, 42, 12), Decl(a.js, 52, 2)) +>Multimap3 : Symbol(Ns.Multimap3, Decl(a.js, 42, 12), Decl(a.js, 54, 3)) +>prototype : Symbol(Ns.Multimap3.prototype, Decl(a.js, 52, 2)) + + /** + * @param {K} key the key ok + * @returns {V} the value ok + */ + get(key) { +>get : Symbol(get, Decl(a.js, 54, 26)) +>key : Symbol(key, Decl(a.js, 59, 8)) + + return this._map[key + '']; +>this : Symbol(__object, Decl(a.js, 54, 24)) +>key : Symbol(key, Decl(a.js, 59, 8)) + } +} + + diff --git a/tests/baselines/reference/jsdocTemplateTag5.types b/tests/baselines/reference/jsdocTemplateTag5.types new file mode 100644 index 0000000000000..c5b8752d2b62f --- /dev/null +++ b/tests/baselines/reference/jsdocTemplateTag5.types @@ -0,0 +1,149 @@ +=== tests/cases/conformance/jsdoc/a.js === +/** + * Should work for function declarations + * @constructor + * @template {string} K + * @template V + */ +function Multimap() { +>Multimap : typeof Multimap + + /** @type {Object} TODO: Remove the prototype from the fresh object */ + this._map = {}; +>this._map = {} : {} +>this._map : { [x: string]: V; } +>this : Multimap & { get(key: K): V; } +>_map : { [x: string]: V; } +>{} : {} + +}; + +Multimap.prototype = { +>Multimap.prototype = { /** * @param {K} key the key ok * @returns {V} the value ok */ get(key) { return this._map[key + '']; }} : { get(key: K): V; } +>Multimap.prototype : { get(key: K): V; } +>Multimap : typeof Multimap +>prototype : { get(key: K): V; } +>{ /** * @param {K} key the key ok * @returns {V} the value ok */ get(key) { return this._map[key + '']; }} : { get(key: K): V; } + + /** + * @param {K} key the key ok + * @returns {V} the value ok + */ + get(key) { +>get : (key: K) => V +>key : K + + return this._map[key + '']; +>this._map[key + ''] : any +>this._map : any +>this : { get(key: K): V; } +>_map : any +>key + '' : string +>key : K +>'' : "" + } +} + +/** + * Should work for initialisers too + * @constructor + * @template {string} K + * @template V + */ +var Multimap2 = function() { +>Multimap2 : typeof Multimap2 +>function() { /** @type {Object} TODO: Remove the prototype from the fresh object */ this._map = {};} : typeof Multimap2 + + /** @type {Object} TODO: Remove the prototype from the fresh object */ + this._map = {}; +>this._map = {} : {} +>this._map : { [x: string]: V; } +>this : Multimap2 & { get: (key: K) => V; } +>_map : { [x: string]: V; } +>{} : {} + +}; + +Multimap2.prototype = { +>Multimap2.prototype = { /** * @param {K} key the key ok * @returns {V} the value ok */ get: function(key) { return this._map[key + '']; }} : { get: (key: K) => V; } +>Multimap2.prototype : { get: (key: K) => V; } +>Multimap2 : typeof Multimap2 +>prototype : { get: (key: K) => V; } +>{ /** * @param {K} key the key ok * @returns {V} the value ok */ get: function(key) { return this._map[key + '']; }} : { get: (key: K) => V; } + + /** + * @param {K} key the key ok + * @returns {V} the value ok + */ + get: function(key) { +>get : (key: K) => V +>function(key) { return this._map[key + '']; } : (key: K) => V +>key : K + + return this._map[key + '']; +>this._map[key + ''] : any +>this._map : any +>this : { get: (key: K) => V; } +>_map : any +>key + '' : string +>key : K +>'' : "" + } +} + +var Ns = {}; +>Ns : typeof Ns +>{} : {} + +/** + * Should work for expando-namespaced initialisers too + * @constructor + * @template {string} K + * @template V + */ +Ns.Multimap3 = function() { +>Ns.Multimap3 = function() { /** @type {Object} TODO: Remove the prototype from the fresh object */ this._map = {};} : typeof Multimap3 +>Ns.Multimap3 : typeof Multimap3 +>Ns : typeof Ns +>Multimap3 : typeof Multimap3 +>function() { /** @type {Object} TODO: Remove the prototype from the fresh object */ this._map = {};} : typeof Multimap3 + + /** @type {Object} TODO: Remove the prototype from the fresh object */ + this._map = {}; +>this._map = {} : {} +>this._map : { [x: string]: V; } +>this : Multimap3 & { get(key: K): V; } +>_map : { [x: string]: V; } +>{} : {} + +}; + +Ns.Multimap3.prototype = { +>Ns.Multimap3.prototype = { /** * @param {K} key the key ok * @returns {V} the value ok */ get(key) { return this._map[key + '']; }} : { get(key: K): V; } +>Ns.Multimap3.prototype : { get(key: K): V; } +>Ns.Multimap3 : typeof Multimap3 +>Ns : typeof Ns +>Multimap3 : typeof Multimap3 +>prototype : { get(key: K): V; } +>{ /** * @param {K} key the key ok * @returns {V} the value ok */ get(key) { return this._map[key + '']; }} : { get(key: K): V; } + + /** + * @param {K} key the key ok + * @returns {V} the value ok + */ + get(key) { +>get : (key: K) => V +>key : K + + return this._map[key + '']; +>this._map[key + ''] : any +>this._map : any +>this : { get(key: K): V; } +>_map : any +>key + '' : string +>key : K +>'' : "" + } +} + + diff --git a/tests/cases/conformance/jsdoc/jsdocTemplateTag4.ts b/tests/cases/conformance/jsdoc/jsdocTemplateTag4.ts new file mode 100644 index 0000000000000..adbf6bfbaca0c --- /dev/null +++ b/tests/cases/conformance/jsdoc/jsdocTemplateTag4.ts @@ -0,0 +1,63 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @strict: true +// @Filename: a.js + +/** + * Should work for function declarations + * @constructor + * @template {string} K + * @template V + */ +function Multimap() { + /** @type {Object} TODO: Remove the prototype from the fresh object */ + this._map = {}; +}; + +/** + * @param {K} key the key ok + * @returns {V} the value ok + */ +Multimap.prototype.get = function (key) { + return this._map[key + '']; +} + +/** + * Should work for initialisers too + * @constructor + * @template {string} K + * @template V + */ +var Multimap2 = function() { + /** @type {Object} TODO: Remove the prototype from the fresh object */ + this._map = {}; +}; + +/** + * @param {K} key the key ok + * @returns {V} the value ok + */ +Multimap2.prototype.get = function (key) { + return this._map[key + '']; +} + +var Ns = {}; +/** + * Should work for expando-namespaced initialisers too + * @constructor + * @template {string} K + * @template V + */ +Ns.Multimap3 = function() { + /** @type {Object} TODO: Remove the prototype from the fresh object */ + this._map = {}; +}; + +/** + * @param {K} key the key ok + * @returns {V} the value ok + */ +Ns.Multimap3.prototype.get = function (key) { + return this._map[key + '']; +} diff --git a/tests/cases/conformance/jsdoc/jsdocTemplateTag5.ts b/tests/cases/conformance/jsdoc/jsdocTemplateTag5.ts new file mode 100644 index 0000000000000..0bfb6b7ca373a --- /dev/null +++ b/tests/cases/conformance/jsdoc/jsdocTemplateTag5.ts @@ -0,0 +1,70 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @strict: true +// @Filename: a.js + +/** + * Should work for function declarations + * @constructor + * @template {string} K + * @template V + */ +function Multimap() { + /** @type {Object} TODO: Remove the prototype from the fresh object */ + this._map = {}; +}; + +Multimap.prototype = { + /** + * @param {K} key the key ok + * @returns {V} the value ok + */ + get(key) { + return this._map[key + '']; + } +} + +/** + * Should work for initialisers too + * @constructor + * @template {string} K + * @template V + */ +var Multimap2 = function() { + /** @type {Object} TODO: Remove the prototype from the fresh object */ + this._map = {}; +}; + +Multimap2.prototype = { + /** + * @param {K} key the key ok + * @returns {V} the value ok + */ + get: function(key) { + return this._map[key + '']; + } +} + +var Ns = {}; +/** + * Should work for expando-namespaced initialisers too + * @constructor + * @template {string} K + * @template V + */ +Ns.Multimap3 = function() { + /** @type {Object} TODO: Remove the prototype from the fresh object */ + this._map = {}; +}; + +Ns.Multimap3.prototype = { + /** + * @param {K} key the key ok + * @returns {V} the value ok + */ + get(key) { + return this._map[key + '']; + } +} +