137

Previously I've always documented my object parameters as follows:

/**
 * Description of the function
 *
 * @param {Object} config - The configuration
 * @param {String} config.foo
 * @param {Boolean} [config.bar] - Optional value
 * @return {String}
 */
function doSomething (config = {}) {
  const { foo, bar } = config;
  console.log(foo, bar);
  // do something
}

But I am unsure what the best approach is with desctructured function parameter. Do I just ignore the object, define it somehow or what is the best way of documenting it?

/**
 * Description of the function
 *
 * @param {String} foo
 * @param {Boolean} [bar] - Optional value
 * @return {String}
 */
function doSomething ({ foo, bar } = {}) {
  console.log(foo, bar);
  // do something
}

I feel like my approach above doesn't make it obvious that the function expects an object and not two different parameter.

Another way I could think of would be using @typedef, but that might end up being a huge mess (especially in a larger file with many methods)?

/**
 * @typedef {Object} doSomethingConfiguration
 * @property {String} foo
 * @property {Boolean} [bar] - Optional value
 */

/**
 * Description of the function
 *
 * @param {doSomethingConfiguration}
 * @return {String}
 */
function doSomething ({ foo, bar } = {}) {
  console.log(foo, bar);
  // do something
}
morkro
  • 4,336
  • 5
  • 25
  • 35
  • 1
    I think the first approach is still fine. Nobody cares whether the object is named `config` in your code or does have any name at all. – Bergi Jun 10 '16 at 13:36
  • In WebStorm I have found that if I just describe the (after-destructuring) parameters and ignore the destructuring it mostly works except for less-common cases. So in your example, describe two parameters `foo` and `bar`. It's not a final solution, but any approach using an object yielded inspection errors - and inspections and autocompletions from the IDE is what I care about most. – Mörre Jun 11 '16 at 10:52

3 Answers3

160

This is how it's intended, as described in the documentation.

/**
 * My cool function.
 *
 * @param {Object} obj - An object.
 * @param {string} obj.prop1 - Property 1.
 * @param {string} obj.prop2 - Property 2.
 */
const fn = function ({prop1, prop2}) {
  // Do something with prop1 and prop2
}

So, your first example is pretty much correct.

Another example with some deeper nesting:

/**
 * Nesting example.
 *
 * @param {Object} param
 * @param {number} param.a - First value
 * @param {Object} param.b - Wrapper
 * @param {number} param.b.c - Second value
 * @return {number} sum a and b
 */
const letters = ({a, b: {c}}) => a + c;
Cerbrus
  • 70,800
  • 18
  • 132
  • 147
  • I don't see how JSDoc unambiguously works when you have multiple destructured arguments, like `function ({a}, {a}) {}`. The JSDoc I guess would be `@param {object} param1, @param {*} param1.a, @param {object} param2, @param {*} param2.a`, and rely on ordering of the `@param` tags? – ZachB Apr 25 '18 at 23:52
  • 1
    @ZachB: `function ({a}, {a}) {}` is invalid syntax, since `a` is defined twice, there. – Cerbrus Apr 26 '18 at 05:38
  • 2
    Oops. `({a: b}, {a}))` or `({a}, {b})` -- point was that JSDoc `@param` tags are orderless AFAIK and the keys can be ambiguous were JSDoc to try to match using property names. The next version of VSCode is going to use positional lookup to resolve this scenario. – ZachB Apr 26 '18 at 10:23
  • 1
    With this I get the eslint warning: "Missing JSDoc parameter description for 'param'." (valid-jsdoc) – Jean Paul Apr 09 '21 at 14:58
  • @JeanPaul: then you need to add a description – Cerbrus Apr 09 '21 at 16:21
  • I'm getting `The type of a function declaration must match the function's signature.` from VS Code ts engine with that. – connexo Jul 04 '21 at 17:15
  • For multiple parameters, just add the name(no type will use whatever is detected). const letters = (d, {a, b: {c}}) => a + c; Add [at]param {number} d Or [at]param d to not override type. – Damien Golding Mar 04 '22 at 03:16
  • @Cerbrus any reason why you're capitalizing `Object` in the first snippet, but not in the second? – jjmerelo Jul 26 '23 at 10:42
  • 1
    @jjmerelo no, that was a typo – Cerbrus Jul 26 '23 at 11:21
33

I personally use this one:

/**
* @param {{
  a: number
  b: number
}} param0
* @returns {number} The sum
*/
const func = ({ a, b }) => a + b;

Just create the object right there.

I also take advantage of TypeScript, and would declare obtional b as b? or b: number | undefined as JSDoc also allows unions

Coding Edgar
  • 1,285
  • 1
  • 8
  • 22
  • For multiple parameters, just add the name(no type will use whatever is detected). const letters = (d, {a, b: {c}}) => a + c; Add [at]param {number} d Or [at]param d to not override type. – Damien Golding Mar 04 '22 at 03:17
-7

See JSDoc's "Documenting a parameter's properties":

/**
 * Assign the project to an employee.
 * @param {Object} employee - The employee who is responsible for the project.
 * @param {string} employee.name - The name of the employee.
 * @param {string} employee.department - The employee's department.
 */
Project.prototype.assign = function(employee) {
    // ...
};

(Google Closure compiler type checking, that was based on but diverted from JSDoc, also allows @param {{x:number,y:number}} point A "point-shaped" object.)

Jakub Holý
  • 6,019
  • 3
  • 33
  • 33
  • 2
    Isn't he already doing that? He is asking what to do now that there is no `employee` variable in the function any more. – Bergi Jun 10 '16 at 13:35
  • 8
    This doesn't answer the question - this example does not use destructuring! With destructuring you have no parent object. – Mörre Jun 11 '16 at 10:50
  • Actually his same link, right after his example gives a relative example with the same exact jsdoc comments for `Project.prototype.assign = function({ name, department })`. Prior to the example they say, "If a parameter is destructured without an explicit name, you can give the object an appropriate one and document its properties." – notacouch Oct 28 '18 at 20:59