Björn Morén
Björn Morén

Reputation: 773

How to write comments on a @typedef for Closure compiler?

Here is how you define a custom type, from the Closure compiler documentation:

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

How do I add comments to explain what each property does, preferably on the same line as each property?

Upvotes: 0

Views: 25

Answers (1)

Colin Alworth
Colin Alworth

Reputation: 18331

A @typedef can certainly be used this way, but consider a @record instead - and if needed, @typedef the record to another name. You can add more remarks in the jsdoc block you've written already, but not specifically for each member.

What you've built here is an anonymous structural type, and then used typedef to give it a (new) name. Specifically, this is a record type when defined using this "object literal" syntax.

Instead, consider defining an explicit type, such as with @record, allowing you to add more remarks :

/**
 * A short note about what this structural interface is for.
 * @record
 */
function Mytype() {}
/**
 * A string, used for foo things.
 * @type {string}
 */
Mytype.prototype.foo;
/**
 * The number of a bar, or something.
 * @type {number}
 */
Mytype.prototype.bar;
/**
 * A field with a union type
 * @type {number|string}
 */
Mytype.prototype.foobar;

Be aware that structural types can have implications on the rest of your program - it may be beneficial to define a nominal type (e.g. a class with a constructor) to give the compiler more knowledge and control over what the code can be allowed to do. Simply changing the above to be declared as an @interface or using a @constructor (possibly as an es5 class) will be enough to declare such a type - but then you must use it, instead of passing object literals. It will have the advantage of avoiding permitting the compiler to consider two unrelated types (where has a subset of the fields of the other) as being related, and thus allowing the "wrong" type to be substituted. Beyond allowing "the wrong type" to be passed, it also prevents some optimizations from being applied. Simple example: if one type is never directly instantiated, uses of that type can always be marked as null, but if a subtype apparently exists and is used, then those usages can't be optimized out.

Upvotes: 1

Related Questions