6

JSDoc 3's documentation includes this example:

/**
 * The complete Triforce, or one or more components of the Triforce.
 * @typedef {Object} WishGranter~Triforce
 * @property {boolean} hasCourage - Indicates whether the Courage component is present.
 * @property {boolean} hasPower - Indicates whether the Power component is present.
 * @property {boolean} hasWisdom - Indicates whether the Wisdom component is present.
 */

/**
 * A class for granting wishes, powered by the Triforce.
 * @class
 * @param {...WishGranter~Triforce} triforce - One to three {@link WishGranter~Triforce} objects
 * containing all three components of the Triforce.
 */
function WishGranter() {}

I am essentially creating a class that takes an object that implements an interface MessageQueueConnector, which should have one method connectAndSubscribe implemented. Since Javascript does not distinguish between member functions and member variables, it makes sense to use property, and JSDoc's documentation implies that @method is unrelated. However, method sound a lot more correct so I'm wondering if this is preferred, or if I'm just doing all of this wrong anyway (i.e. if there is a simpler way to document this situation in the first place, without creating a type).

djechlin
  • 54,898
  • 29
  • 144
  • 264

3 Answers3

11

@typedef is extremely limited in what it can do. You could define the methods as properties but then you would not be able to document parameters in the same way you would on a real class. What I've done to get around this limitation is to cheat. I use @class so that I can document it the way I want and put a warning that it is not a real class. So:

/**
 * @classdesc Not a real class but an interface. Etc...
 *
 * @name MessageQueueConnector
 * @class
 */

/**
 * This method does...
 *
 * @method
 * @name MessageQueueConnector#connectAndSubscribe
 * @param {string} whatever Whatever this is.
 * @returns {Object} Description of return value.
 * @throws {SomeException} blah.
 */

Note that the two doclets above do not need to have any associated JavaScript code. You don't need to create a fake class in JavaScript, you don't need to create a fake method, etc. This is why you need to use @name.

I don't like telling jsdoc that this is a class and then put in the doc that it is not but I found this to be the least objectionable way to get jsdoc to do what I want. I expect this workaround to become obsolete eventually as jsdoc evolves.

Louis
  • 128,628
  • 25
  • 249
  • 295
1

I'm currently using BOTH:

  • @tryAnyTag in the method comment, and
  • @property in the class comment
    • Since only method comments have namepaths (@property tags in class comments do not), we insert the namepath of the method comment as the description of the @property.

Example:

/** @module Example */

/**
 * @class module:Example.Car
 * @property {Function} start {@link module:Example.Car#start}
 * @property {Function} stop {@link module:Example.Car#stop}
 *
 */
class Car {

    /**
    * @method module:Example.Car#start
    *
    */
    function start () { /* function body */ }

    /**
    * @description You could use various other tags here, 
    * and JSDoc will still auto-assign the following namepath 
    * "module:Example.Car#stop" to this method
    *
    */
    function stop () { /* function body */ }
}

It's unfortunate that documenters have to pull double-duty because the JSDoc compiler doesn't automatically figure this out. At some point, there should be only one way to do this all at once - but it would imply breaking changes to the JSDoc compiler.

jerng
  • 439
  • 5
  • 13
0

Another option would be to use @typedef to define a callback for each method. Then, in your @typedef for the object in question, define each method using the @property tag and supply the callback name paths as the property types. These would show up in the generated documentation as members rather than methods, but they would at least include information about the parameters and return values.

Daniel Arant
  • 463
  • 1
  • 4
  • 14