244

How can I tell JSDoc about the structure of an object that is returned. I have found the @return {{field1: type, field2: type, ...}} description syntax and tried it:

/**
 * Returns a coordinate from a given mouse or touch event
 * @param  {TouchEvent|MouseEvent|jQuery.Event} e    
 *         A valid mouse or touch event or a jQuery event wrapping such an
 *         event. 
 * @param  {string} [type="page"]
 *         A string representing the type of location that should be
 *         returned. Can be either "page", "client" or "screen".
 * @return {{x: Number, y: Number}} 
 *         The location of the event
 */
var getEventLocation = function(e, type) {
    ...

    return {x: xLocation, y: yLocation};
}

While this parses successfully, the resulting documentation simply states:

Returns: 
    The location of an event
    Type: Object

I am developing an API and need people to know about the object that they will get returned. Is this possible in JSDoc? I am using JSDoc3.3.0-beta1.

BlackWolf
  • 5,239
  • 5
  • 33
  • 60
  • I know that `@typedef` is a workaround/solution, but it seems weird for this to not work with literal objects. If anyone stumbles upon this in the future (as I did) I've added an issue https://github.com/jsdoc/jsdoc/issues/1678 that could have more info than this page. – Zefir Aug 23 '19 at 11:17

3 Answers3

401

Define your structure separately using a @typedef:

/**
 * @typedef {Object} Point
 * @property {number} x - The X Coordinate
 * @property {number} y - The Y Coordinate
 */

And use it as the return type:

/**
 * Returns a coordinate from a given mouse or touch event
 * @param  {TouchEvent|MouseEvent|jQuery.Event} e    
 *         A valid mouse or touch event or a jQuery event wrapping such an
 *         event. 
 * @param  {string} [type="page"]
 *         A string representing the type of location that should be
 *         returned. Can be either "page", "client" or "screen".
 * @return {Point} 
 *         The location of the event
 */
var getEventLocation = function(e, type) {
    ...

    return {x: xLocation, y: yLocation};
}
mkobit
  • 43,979
  • 12
  • 156
  • 150
BGerrissen
  • 21,250
  • 3
  • 39
  • 40
  • 2
    Thanks. Multiple `@return` statements do indeed work, but they are listed in the output as if they were several returns (One bullet point states `point - Object` and then two other bullet points for `point.x - Number` and `point.y - Number`). While I can live with that, I suppose there is no way of having a condensed output of the returned object? Or at the very least have the entries for `point.x` and `point.y` indented? – BlackWolf Feb 27 '15 at 11:20
  • 1
    Yes, that does seem like the best option. I thought there might be a way to have a non-named return entity, but the `@typedef` approach is the most clear one in terms of documentation output, thanks! – BlackWolf Feb 27 '15 at 12:07
  • groovy, removed the first option as 2nd option is simply best. – BGerrissen Feb 27 '15 at 12:15
  • 3
    You better add `@inner` or type definition will have `global` scope in the documentation. +1 – Onur Yıldırım Jun 05 '16 at 23:38
  • 1
    I've always used `@typedef {Object} Point`. In fact, using this two-line form highlights `Point` in PhpStorm with the message "Unresolved variable or type Point". The [`@typedef` docs](http://usejsdoc.org/tags-typedef.html) support this, but I don't want to edit this answer if it's a valid variant. – David Harkness Jul 20 '16 at 04:53
  • @DavidHarkness Yes, explicitly defining `{Object}` before the type name seems to be the correct way to do it. – Tim Visée Aug 21 '16 at 16:54
  • Lovely to see this is supported in Google App Script as well. – Code Poet Apr 26 '22 at 15:08
50

An alternative to the suggestions already posted, you can use this format:

/**
 * Get the connection state.
 *
 * @returns {Object} connection The connection state.
 * @returns {boolean} connection.isConnected Whether the authenticated user is currently connected.
 * @returns {boolean} connection.isPending Whether the authenticated user's connection is currently pending.
 * @returns {Object} connection.error The error object if an error occurred.
 * @returns {string} connection.error.message The error message.
 * @returns {string} connection.error.stack The stack trace of the error.
 */
getConnection () {
  return {
    isConnected: true,
    isPending: false,
    error
  }
}

which will give the following documentation output:

    Get the connection state.

    getConnection(): Object

    Returns
    Object: connection The connection state.
    boolean: connection.isConnected Whether the authenticated user is currently connected.
    boolean: connection.isPending Whether the authenticated users connection is currently pending.
    Object: connection.error The error object if an error occurred.
    string: connection.error.message The error message.
    string: connection.error.stack The stack trace of the error.
Matt Pengelly
  • 1,480
  • 2
  • 20
  • 34
  • 1
    this leads to _"method returns Object OR String OR Boolean"_ - every `@returns` adds a new return-option, instead of descriptions for fields of the returned object. – maxkoryukov Aug 10 '22 at 02:53
22

A clean solution is to write a class and return that.

/** 
 *  @class Point
 *  @type {Object}
 *  @property {number} x The X-coordinate.
 *  @property {number} y The Y-coordinate.
 */
function Point(x, y) {
  return {
        x: x,
        y: y
    };
}

/**
 * @returns {Point} The location of the event.
 */
var getEventLocation = function(e, type) {
    ...
    return new Point(x, y);
};
mooses
  • 558
  • 6
  • 9
  • When I do this but use the Google Closure Compiler, I get a warning: "cannot instantiate non-constructor". I tried adding @constructor to the function (above the @return) but it didn't help. If someone knows how to fix that, please let me know. Thanks! – Johann Jun 20 '17 at 17:23
  • 2
    @AndroidDev this is because the function `Point` is not a constructor, to change that replace the body of the `Point` function with `this.x = x; this.y = y;` – Feirell Apr 18 '18 at 21:00
  • 1
    I don't see the reason why we need to use new here, why not just return Point(x, y)? – CHANist Sep 07 '19 at 04:43
  • @CHANist, `new` syntax is to create an instance from the `constructor`. Without `new`, the context of `this` would be the global context. You can try creating an instance without `new` to see the effect. – Aakash Mar 21 '20 at 02:43
  • You forgot to describe the `@returns` on your `Point` JSDocs. – Roko C. Buljan Mar 11 '22 at 00:02