Skip to content
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

Intellisense for object properties defined in multi-line JSDoc comments #11597

Closed
abgivant opened this issue Oct 13, 2016 · 24 comments · Fixed by #17352
Closed

Intellisense for object properties defined in multi-line JSDoc comments #11597

abgivant opened this issue Oct 13, 2016 · 24 comments · Fixed by #17352
Assignees
Labels
Domain: JSDoc Relates to JSDoc parsing and type generation Suggestion An idea for TypeScript VS Code Tracked There is a VS Code equivalent to this issue

Comments

@abgivant
Copy link

Currently it doesn't look like the TypeScript parser recognizes properties for an object parameter if they are defined with separate @param declarations. Would it be possible to add support for this?

image

image

Thanks!

@Jessidhia
Copy link

A workaround is to write:

/**
 * @param {{strProp: string, numProp: number}} obj - An object parameter with string and number properties
 */

but that doesn't allow for documenting the specific subkeys.

@abgivant
Copy link
Author

abgivant commented Jan 6, 2017

@Kovensky Yeah, that does work, but the individual property documentation is the main reason I prefer the multi-line documenting.

@abgivant abgivant reopened this Jan 16, 2017
@abgivant
Copy link
Author

Sorry, didn't mean to close/reopen this...

@ryansully
Copy link

Would a solution to this also support destructured parameters as well?
Example: jsdoc/jsdoc#987 (comment)

@abgivant
Copy link
Author

abgivant commented Mar 22, 2017

I haven't really used that pattern, but I would think it would. That seems to be an extension of the same underlying issue of being unable to document properties of object parameters.

@ankitsny
Copy link

How about creating a @typedef
this works fine for me.

/**
 * @typedef {Object} GetUsersParams
 * @property {number} page_size          - Number of results to show in a page, optional?
 * @property {number} page_number        - Page number, optional?
 * @property {Object} match_params       - match query, optional?
 */
/**
 * @description getUsers function can be used to fetch users
 * @param {GetUsersParams} params - Provide appropriate props
 * @param {function} cb
 */
function getUsers(params, cb) {
    // do something
}

I tried this, but it doesn't work

* @param {...GetUsersParams} params 

@abgivant
Copy link
Author

That's actually what I've been doing as a workaround, but it doesn't allow for documenting optional/default values.

You also don't get the text descriptions in intellisense. I wouldn't say that's necessary, but it'd be nice.

@MikeyBurkman
Copy link

Has there been any update on this? The @typedef workaround is not bad, but without the support of optional parameters (which seem to be supported for jsdocs), I'm getting a lot of false positives with jscheck turned on.

@mhegazy
Copy link
Contributor

mhegazy commented May 17, 2017

but without the support of optional parameters (which seem to be supported for jsdocs)

can you elaborate on this?

@MikeyBurkman
Copy link

MikeyBurkman commented May 17, 2017

@mhegazy Here's a code snippet:

/**
 * @typedef {Object} Opts
 * @property {string} x
 * @property {string=} y
 * 
 * @param {Opts} opts
 */
function foo(opts) {
  console.log(opts);
}

foo({x: 'abc'});

That call to foo() will be flagged because it's missing y in the opts. The type checker does not recognize any of the methods of specifying optional parameters listed on the wiki. I even tried doing TS-style using @property {string?} y and still no luck.

EDIT: Doing @property {string} [y] actually causes the type checker to ignore the existence of the y parameter altogether.

@mhegazy
Copy link
Contributor

mhegazy commented May 17, 2017

I think that is another bug. thanks for reporting it. filed #15916 to track it.

@sandersn sandersn moved this from Not started to In Progress in Rolling Work Tracking Jun 29, 2017
@zanza00
Copy link

zanza00 commented Jul 11, 2017

I have a similar problem with stateless functional components in react, they are written with object destructuring and the trick with @typedef doesn't works because the parameter doesnt have a proper name

I have tried with props, param0 , args0 but no luck 😞

/**
 * @typedef Props
 * @property {string} one  - first 
 * @property {number} two  - second
 * 
 * @param {Props} props
 */

// doesn't work
function Component({one, two}) { 
// stuff... 
}

// works
function Component(props) { 
const {one, two} = props
// stuff... 
}

thanks for any advice 😄

@sandersn
Copy link
Member

@zanza00 you can you specify the type inline:

function Component(/** @type {Props} */ { one, two }) {
 // stuff ...
}

@zanza00
Copy link

zanza00 commented Jul 18, 2017

I can confirm that indeed it works, thanks

@sandersn
Copy link
Member

Fix is up at #17352

@mohsen1
Copy link
Contributor

mohsen1 commented Apr 8, 2018

@sandersn It's still not possible to have a destructured parameter with @param annotations.

Example:

 /**
  * @typedef BarBaz
  * @property {string} bar
  * @property {string} baz
  */

/**
 * @param {BarBaz} options Your configuration object
 */
function foo({bar, baz}) {

}

Error

 error TS8024: JSDoc '@param' tag has name 'options', but there is no parameter with that name.

338  * @param {BarBaz} options Your configuration object
                       ~~~~~~~

I can change my code to:

function foo(/** @type {BarBaz} */{bar, baz}) {

}

but then where should I put the parameter description text?

Also see webpack/webpack#6988

@sandersn
Copy link
Member

sandersn commented Apr 9, 2018

@mohsen1 that’s a slightly different issue than this one, and is tracked at #19645.

The PR with the fix is at #18832. I’ll take another look at it; last I remember we needed to check whether performance was OK with the additional upfront processing and storage it required.

@sandersn
Copy link
Member

@mohsen1 destructured parameters now look up jsdoc @param tags positionally. It should be available tomorrow in typescript@next.

@Shahor
Copy link

Shahor commented Apr 27, 2018

What do you mean by positionally?

Are we heading towards something like

/**
* @param {number} $0.id An id
*/
function foo({ id }) {}

?

@sandersn
Copy link
Member

@Shahor no the syntax you would use is either

/**
 * @param {Object} arg
 * @param {number} arg.id An id
 */
function foo({ id }) {}

OR

/**
 * @param {{ id: number }} arg
 */
function foo({ id }) {}

@steph643
Copy link

steph643 commented Jun 6, 2018

@sandersn, the two syntaxes you've suggested above doesn't seem to work. See here.

@sandersn
Copy link
Member

sandersn commented Jun 6, 2018

@steph643 VS code 1.23 is running Typescript 2.8, which doesn't have the fix.

@Shagon94
Copy link

can confirm the issue, example code:

/**
 * @param {*} options the args object
 * @param {number} object.alpha first number
 * @param {number} object.bravo second number
 * @param {Function} callback the callback function
 * @returns {number}
 */
function addNumbersFromObject({ alpha = 1, bravo = 2 } = {}, callback = null) {
  if (!callback) return alpha + bravo;
  return callback(alpha + bravo);
}

console.log(addNumbersFromObject({ alpha: 2 }));

that results in the text not being displayed:
screen shot 2018-06-14 at 10 26 29 am

The workaround is to use the @typedef like so:

/**
 * @typedef {Object} Opts
 * @property {string} alpha Alpha helping test
 * @property {string=} bravo Description about bravo
 * 
 * @param {Opts} opts the options object
 * @param {Function} callback the callback function
 * @returns {number}
 */
function addNumbersFromObject({ alpha = 1, bravo = 2 } = {}, callback = null) {
  if (!callback) return alpha + bravo;
  return callback(alpha + bravo);
}

console.log(addNumbersFromObject({ bravo: 2 }));

Now intellisense detects the parameters as well as shows if its an optional parameter and adds description to it:
screen shot 2018-06-14 at 10 29 07 am

@mhegazy
Copy link
Contributor

mhegazy commented Jun 14, 2018

@Shagon94 it should be:

/**
 * @param {Object} options the args object
 * @param {number} options.alpha first number
 * @param {number} options.bravo second number
 * @param {Function} callback the callback function
 * @returns {number}
 */
function addNumbersFromObject({ alpha = 1, bravo = 2 } = {}, callback = null) {
    if (!callback) return alpha + bravo;
    return callback(alpha + bravo);
}

console.log(addNumbersFromObject({ alpha: 2 }));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Domain: JSDoc Relates to JSDoc parsing and type generation Suggestion An idea for TypeScript VS Code Tracked There is a VS Code equivalent to this issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.