Document generic type parameters in JSDOC

You can try using @template tag (undocumented tag used in Google Closure library - extremely limited form of generics). Something like:

/**   
 * Search an array for the first element that satisfies a given condition and   
 * return that element.   
 * @param {Array.<T>|goog.array.ArrayLike} arr Array or array   
 *     like object over which to iterate.   
 * @param {?function(this:S, T, number, ?) : boolean} f The function to call   
 *     for every element. This function takes 3 arguments (the element, the   
 *     index and the array) and should return a boolean.   
 * @param {S=} opt_obj An optional "this" context for the function.   
 * @return {T} The first array element that passes the test, or null if no   
 *     element is found.   
 * @template T,S   
 */  
goog.array.find = function(arr, f, opt_obj) {    
   var i = goog.array.findIndex(arr, f, opt_obj);    
   return i < 0 ? null : goog.isString(arr) ? arr.charAt(i) : arr[i];  
}; 

WebStorm uses this tag for type hinting - i.e. if we pass array of strings to goog.array.find in the sample above , IDE will know that return type is string, so string completion options will be suggested etc.

Not sure if this is what you are looking for... The post that looks related is here.


In the meantime, support for this feature has been finalized and is now documented on the Closure Compiler JSDOC page for generics.

Basically it works like this for ES6 classes:

/** @template T */
class Foo {
  /** @return {T} */
  get() { ... };

  /** @param {T} t */
  set(t) { ... };
}

... and like this for pre-ES6 code:

/**
 * @constructor
 * @template T
 */
Foo = function() { ... };

and

/** @return {T} */
Foo.prototype.get = function() { ... };

/** @param {T} t */
Foo.prototype.set = function(t) { ... };

WebStorm 7.0 did not support this feature at the time the original answer was written, but as of today (2019) all JetBrains IDEs understand this syntax, properly.


The following code works fine for me in WebStorm 8.

/** @type {Array.<MyPair.<Event, Array.<Thought>>>} */
scope.pairs = [];

/**
 * @template TFirst, TSecond
 */
function MyPair(first, second){
    this.first = first;
    this.second = second;
}
/** @type {TFirst} */
MyPair.prototype.first = null;
/** @type {TSecond} */
MyPair.prototype.second = null;

...
function Event(){}
...
...
function Thought(){}
...