14

I'm writing my own library for the project at work for a browser application and I am having the same old problem deciding how to comment the code.

I'm trying to follow the JsDoc syntax, but will probably continue the Google Closure Compiler way. I may end up using two @return and @returns tags in the documentation, just for portability sake (when I setup the auto-generation of the documentation).

Now, the question, how do you document the return of a custom anonymous object from a function? For example:

return {
    username: 'username',
    password: 'password',
    enabled:  true
};

JsDoc has an example of how a @param can be documented to expect object with certain fields, but not the @returns tag. Similarly, the Google Closure Compiler documentation of a Record Type is vague and has no example to work it out.

Azder
  • 4,698
  • 7
  • 37
  • 57
  • The return type is `Object`. Why don't you simply describe the object structure in a few lines like you would for a parameter? – jwueller Jun 20 '12 at 10:16
  • See https://developers.google.com/closure/compiler/docs/js-for-compiler#types – Rob W Jun 20 '12 at 10:17
  • @elusive Yes, I can always do that, the point is to allow for the compiler to have info it can work with, not just for humans to read. – Azder Jun 20 '12 at 11:02

3 Answers3

15

The Closure-compiler uses a subset of the JSDoc annotations (and adds a few of its own). See the annotation reference for the compiler for the complete set. A JSDoc annotation is similar to a JavaDoc annotation and is a comment block that begins with /** (two stars). While each line of the comment often begins with it's own *, that is a convention that is not required. Only one JSDoc tag is allowed per line, but the arguments for a tag can span multiple lines.

The annotation typically applies to the following statement. Here are some examples:

Variable

/** @type {string} */ var a;

Type Cast

var b = /** @type {string} */ (window['foo']);

note the extra parenthesis

Named Function

/**
 * @param {string} bar
 * @return {boolean}
 */
function foo(bar) { return true; }

Function Expressions

/** @type {function(string):boolean} */
var foo = function(bar) { return true; }

var foo2 =
  /**
   * @param {string} bar
   * @return {boolean}
   */
  function(bar) { return true; }

Typedef

Complex types (including unions, and record types) can be aliased for convenience and maintainability using a typedef. These annotations can be long, but can be split over multiple lines for readability.

/** @typedef {{
 *             foo:string,
 *             bar:number,
 *             foobar:number|string
 *           }}
 */
var mytype;

For your original example, there are several possible ways to annotate such a function return value. One of the most specific and still convenient is the record type:

/** @return {{username:string, password:string, enabled:boolean}} */
function() {
  return {
    username: 'username',
    password: 'password',
    enabled:  true
  }
}

Note the extra {}. Also keep in mind that record types will not prevent property renaming.

This annotation tells the compiler that the function returns an anonymous type with username, password and enabled properties. Other valid options would be to define an interface elsewhere and typecast the return value to be that interface. The least specific annotation would be Object or *.

To see a wide range of possible annotations, take a look at the extern files in the Compiler project.

Chad Killingsworth
  • 14,360
  • 2
  • 34
  • 57
  • I actualy read it before asking, and have used the google closure compiler in the past. Still I'm unclear of how to proceed. Imagine the need to document 20 fields in a multiline. Do I put asterisk (*) at the begining of each line? More tests underway. – Azder Jun 20 '12 at 12:27
  • The compiler uses JSDoc annotations. I'll update the answer to be more complete. – Chad Killingsworth Jun 20 '12 at 14:09
  • @ChadKillingsworth Hi Chad, sorry to barge in on an old thread but this scores high in google `closure annotations multi line`. I'm looking how to annotate complex types with @typedef. The annotation can't be spread out over multiple lines (I think) but it would make a complex typedef more readable. For example `{{hands:number,walk:function(number):boolean,stop:function():boolean ... and lots more ...}}` – HMR Jun 07 '13 at 07:37
  • Single annotations can span more than one line. I added an example for typedefs. – Chad Killingsworth Jun 07 '13 at 12:33
5

One of the nice and portable ways to do it is like the following, using return as a keyword. https://github.com/senchalabs/jsduck/wiki/%40return

/**
 * @return {object} return An object with the following properties
 * @return {string} return.username Some username
 * @return {string} return.password Some password
 * @return {boolean} return.enabled Is the user enabled?
 */
function getObj () {
     return {
         username: 'username',
         password: 'password',
         enabled:  true
      };
}

If you have to use it in multiple places, you would have to duplicate it, or use @typedef, but I haven't figured out how to add comments to @typedef so I use something like the following

/**
 * @typedef {username:string, password:string, enabled:boolean} MyType
 *  
 *  username: The name of the user 
 *  password: Some password
 *  enabled: Is the user enabled?
 */

/**
 * @return {MyType}
 */
function getObj () {
     return {
         username: 'username',
         password: 'password',
         enabled:  true
      };
}

You can also try the suggestion here How can I document a type in webstorm using just jsdoc?

Community
  • 1
  • 1
Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
1

If put this in top of the function

function myFunction() {
    /**
     * Description of my function
     * @return {!Object.<string, string|boolean>} Returns an object containing username, password and enabled information
     */

    // Do stuff
    return {
        username: 'username',
        password: 'password',
        enabled:  true
    }
}
Sense545
  • 494
  • 4
  • 14
  • 2
    Or above the function, if you prefer that way of notating. (I always put them inside, so if i do .toString() on a function, i can see the documentation) – Sense545 Jun 20 '12 at 10:23