Typescript: Intellisense for object properties defined in multi-line JSDoc comments

Created on 13 Oct 2016  路  24Comments  路  Source: microsoft/TypeScript

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!

JSDoc Suggestion VS Code Tracked

Most helpful comment

@zanza00 you can you specify the type inline:

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

All 24 comments

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.

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

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

Would a solution to this also support destructured parameters as well?
Example: https://github.com/jsdoc3/jsdoc/issues/987#issuecomment-93864964

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.

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 

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.

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.

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

can you elaborate on this?

@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.

I think that is another bug. thanks for reporting it. filed https://github.com/Microsoft/TypeScript/issues/15916 to track it.

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 馃槃

@zanza00 you can you specify the type inline:

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

I can confirm that indeed it works, thanks

Fix is up at #17352

@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 https://github.com/webpack/webpack/pull/6988

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

The PR with the fix is at #18832. I鈥檒l 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.

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

What do you mean by positionally?

Are we heading towards something like

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

?

@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 }) {}

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

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

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

@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 }));
Was this page helpful?
0 / 5 - 0 ratings

Related issues

Antony-Jones picture Antony-Jones  路  3Comments

wmaurer picture wmaurer  路  3Comments

blendsdk picture blendsdk  路  3Comments

zhuravlikjb picture zhuravlikjb  路  3Comments

DanielRosenwasser picture DanielRosenwasser  路  3Comments