Search code examples
javascriptintellij-ideawebstormjsdoc

JSDoc: Typedef from literal


Let's consider the following code, a function that returns an object with two functions:

/**
 * Create a something
 * @returns {object} Something
 */
function createSomething() {
  return {
    /**
     * Foo!
     * @returns {string}
     */
    foo() { return 'foo';},

    /**
     * Bar!
     * @returns {string}
     */
    bar() { return 'bar';}
  };
}

When calling this method, even though the return type is simply object, IDE:s like WebStorm will infer the type from the returned literal, so that typing createSomething(). will suggest members foo and bar. 👍

However, let's say I then need to pass this object around to other functions. For these functions to understand that this is a "something", I'd like to @typedef it, so I do the following:

/**
 * @typedef {object} Something
 */

/**
 * Create a something
 * @returns {Something} Something
 */
function createSomething() {
  return {
    /**
     * Foo!
     * @returns {string}
     */
    foo() { return 'foo';},

    /**
     * Bar!
     * @returns {string}
     */
    bar() { return 'bar';}
  };
}

Now we have a type for the object returned from createSomething(). However, because the return type is explicitly stated, the IDE will NOT automatically infer any members from the returned value, so we now have a defined type without any known members. 👎

I can of course manually enter each member as a @property within the @typedef, like so:

/**
 * @typedef {object} Something
 * @property {function} foo
 * @property {function} bar
 */

However, this means having to keep the typedef in sync manually whenever I add or remove any members from the Something object.

I tried placing the @typedef just above the return statement in createSomething(), hoping that it would hint to JSDoc and the IDE that the typedef has the members defined in the following literal, but to no avail - a @typedef {object} seems to be always treated as having no members other than the explicitly stated @property ones.

Is there a way to let the IDE auto-infer the members from a returned literal, while at the same time defining a type for the returned object? Basically I want the same as what happens when using ES6 classes - it automatically becomes a type with all methods as members.


Solution

  • You may use @lends tag for this before object initializer, like this:

    function createSomething() {
      return /** @lends Something# */ {
        // properties
      }
    }
    
    /** @param {Something} s */
    function f(s) {}
    

    WebStorm understands this. Please note # sign after name in @lends.