Pavel Polyakov
Pavel Polyakov

Reputation: 926

jsdoc @typedef - how to declare function properly?

Here is my jsdoc declaration.

How should I adjust it, so that MyNewType.logFirst property actually references logFirst function, which I've annotated below?

// my-new-type.js
/**
 * MyNewType definition
 * @typedef {Object} MyNewType
 * @property {function} logFirst
 * @property {function} logSecond
 */

/**
 * @param {number} first
 * @param {number} second
 * @returns MyNewType
 */
module.exports = (first, second) => {
  /**
   * logs first argument
   * @param {number} times
   */
  function logFirst(times) {
    for (let i = 0; i < times; i++) {
      console.log(first);
    }
  }

  /**
   * logs second argument
   * @param {number} times
   */
  function logSecond(times) {
    for (let i = 0; i < times; i++) {
      console.log(second);
    }
  }

  return {
    logFirst,
    logSecond
  };
};

It's important, that we keep this kind of "factory" structure.

Currently - this is what I receive: enter image description here

I want my IDE to bind MyNewType.logFirst with logFirst definition.

Upvotes: 30

Views: 31952

Answers (3)

Chen Peleg
Chen Peleg

Reputation: 2124

Only if using Typescript as the type checker, there is a simpler solution IMO:

/** @typedef { (first: number, second: number) => 
{logFirst: (time: number) => void, logSecond: (time : number) => 
void}} MyNewType */

/** @type { MyNewType } */
var MyNewType = module.exports = (first, second) => {
   ...
}

Upvotes: 3

Aghyul Kyoku
Aghyul Kyoku

Reputation: 1060

Unless I'm mistaken, I don't see how the upvoted solution could ever work.

There is nothing like @typedef {MyNewType} MyNewTypein JSDoc, but rather @typedef {Object} MyNewType (to define the base type) (see docs)

Also, annotations are all mixed up in the given solution. For example, @param is only for function parameters and when declaring a specialized function type (see docs)

Last but not least, no offence but the upvoted solution is also wrong because it mixes up the var MyNewType type declaration (a function with two parameters and returning an object with two properties) and the actual returned value declaration (the two properties of the said object). In addition to not including the required brackets around the returned type.

EDIT: oh, I forgot that logFirst is not a number but a Function, which is another mistake in the solution proposed by the OP colleague.

I really cannot fathom why people would upvote such a broken solution...

Being by no means expert in JSDoc, I however think the following solution should fix all that, for new SO visitors:

(NOTE: I don't see why we would ever need two different typedef for the logFirst and logSecond functions as they have the exact same signature, but JFF I specified both)

/**
 * Declare our "logFirst" type (which is a function)
 *
 * @callback TypeFnLogFirst
 * @param {number} times
 * @returns {void}
 */

/**
 * Declare our "logSecond" type (which is a function)
 *
 * @callback TypeFnLogSecond
 * @param {number} times
 * @returns {void}
 */

/**
 * Declare our returned type
 * 
 * @typedef {Object} TypeObjTwoFns
 * @property {TypeFnLogFirst} logFirst
 * @property {TypeFnLogSecond} logSecond
 */

/**
 * Declare our "MyNewType" type (which is a function)
 *     with two parameters
 *     and a return value (object literal of type TypeObjTwoFns)
 *     (==> where the magic happens)
 * Note that "[at]typedef Function" is the same as "[at]callback" (as per the docs)
 *
 * @typedef {Function} TypeFnNewType
 * @param {*} first
 * @param {*} second
 * @returns {TypeObjTwoFns}
 */

/** @type {TypeFnNewType} MyNewType */
var MyNewType = (first, second) => {
    /** @type {TypeFnLogFirst} logFirst */
    function logFirst(times) {
        for (let i = 0; i < times; i++) {
            console.log(first);
        }
    }

    /** @type {TypeFnLogSecond} logSecond */
    function logSecond(times) {
        for (let i = 0; i < times; i++) {
            console.log(second);
        }
    }

    return {
        logFirst,
        logSecond
    };
};

Source: JSDoc typedef,callback,param and JSDoc member,var,type

Upvotes: 48

ProllyGeek
ProllyGeek

Reputation: 15866

Just in case it helps anyone, cause OP is my colleague:

    // my-new-type.js
/**
 * MyNewType definition
 * @typedef {MyNewType} MyNewType
 * @param {number} first
 * @param {number} second
 * @property {function} logFirst
 * @property {function} logSecond
 * @returns MyNewType
 */

var MyNewType = module.exports = (first, second) => {
    /**
     * logs first argument
     * @typedef {number} logFirst
     * @param {number} times
     */
    function logFirst(times) {
        for (let i = 0; i < times; i++) {
            console.log(first);
        }
    }

    /**
     * logs second argument
     * @param {number} times
     */
    function logSecond(times) {
        for (let i = 0; i < times; i++) {
            console.log(second);
        }
    }

    return {
        logFirst,
        logSecond
    };
};

This has worked well for us.

Upvotes: 4

Related Questions