Skip to content

Failing to resolve multiple JSDOC @template tags #46618

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
JacobNorlin opened this issue Nov 1, 2021 · 1 comment · Fixed by #47742
Closed

Failing to resolve multiple JSDOC @template tags #46618

JacobNorlin opened this issue Nov 1, 2021 · 1 comment · Fixed by #47742
Assignees
Labels
Bug A bug in TypeScript Domain: JSDoc Relates to JSDoc parsing and type generation Fix Available A PR has been opened for this issue

Comments

@JacobNorlin
Copy link

Bug Report

Using generics on both an ES5 class and methods results in incomplete type resolution.

🔎 Search Terms

jsdoc, template, generic

🕗 Version & Regression Information

Typescript 4.4.4, 4.5.0-beta

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about JSDoc/generics/templates

⏯ Playground Link

Playground link with relevant code

💻 Code

/**
 * @template {string} T
 * @param {T} t
 */
function Cls(t) {
    this.t = t;
}

/**
 * @template {string} V
 * @param {T} t 
 * @param {V} v 
 */
Cls.prototype.func1 = function (t, v) {
};


Cls.prototype.func2 =
    /**
     * @template {string} V
     * @param {T} t 
     * @param {V} v 
     */
    function (t, v) {
    };

var c = new Cls('a');
c.func1('a', 'b'); //Can't resolve V generic
c.func2('a', 'b'); //Can't T generic in argument

🙁 Actual behavior

Unable to resolve type for all generics defined in the JSDOC

🙂 Expected behavior

All generics should resolve to actual types.

@andrewbranch andrewbranch added Bug A bug in TypeScript Domain: JSDoc Relates to JSDoc parsing and type generation labels Nov 1, 2021
@andrewbranch andrewbranch added this to the TypeScript 4.6.0 milestone Nov 1, 2021
@JacobNorlin
Copy link
Author

A very hacky workaround to this issue is to create a dummy variable typed to the class generic and reference the class generic as this['dummy_variable'] in the method type.

/**
 * @template T
 */
function Foo(){
    /**@type {T} */
    this._hack = undefined;
}

Foo.prototype.test = 
    /**
     * @template V
     * @param {this["_hack"]} t
     * @param {V} v
     */
    function test(t, v){

    };

/**@type {Foo<{p: string}>} */
var a = new Foo();

a.test({p: '123'}, 'test'); 

sandersn added a commit that referenced this issue Feb 4, 2022
1. During name resolution, `@param` and `@return` tags should walk up
through the jsdoc comment and then jump to the host function. Previously they
did not, which would cause them to not resolve type parameters bound in
the scope of a host that was not a sibling of the comment. The example
from #46618 is a prototype method:

```js
/**
 * @template {T}
 * @param {T} t
 */
C.prototype.m = function (t) {
}
```

2. During name resolution, prototype methods are supposed to resolve
types both from the host function's location and from the containing
class' location. The containing class lookup happens in a separate call
to `resolveName`. Previously, the code that finds the containing class
only worked for the above style of comment, which is on the outer
ExpressionStatement, but not for the below style, which is on the
function expression itself:

```js
C.prototype.m =
  /**
   * @template {T}
   * @param {T} t
   */
  function (t) {
}
```
@typescript-bot typescript-bot added the Fix Available A PR has been opened for this issue label Feb 4, 2022
sandersn added a commit that referenced this issue Feb 9, 2022
1. During name resolution, `@param` and `@return` tags should walk up
through the jsdoc comment and then jump to the host function. Previously they
did not, which would cause them to not resolve type parameters bound in
the scope of a host that was not a sibling of the comment. The example
from #46618 is a prototype method:

```js
/**
 * @template {T}
 * @param {T} t
 */
C.prototype.m = function (t) {
}
```

2. During name resolution, prototype methods are supposed to resolve
types both from the host function's location and from the containing
class' location. The containing class lookup happens in a separate call
to `resolveName`. Previously, the code that finds the containing class
only worked for the above style of comment, which is on the outer
ExpressionStatement, but not for the below style, which is on the
function expression itself:

```js
C.prototype.m =
  /**
   * @template {T}
   * @param {T} t
   */
  function (t) {
}
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Domain: JSDoc Relates to JSDoc parsing and type generation Fix Available A PR has been opened for this issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants