jsdoc icon indicating copy to clipboard operation
jsdoc copied to clipboard

[Feature request] Using @returns as type reference

Open shmolf opened this issue 4 years ago • 1 comments

This may be out of scope of what JSDoc is intended to do, or is capable of doing.

Context & Problem

Some of my functions will return an object literal for the sake of convivence or because there are just so few call-sites.

Typically, I will write a @typedef to describe the return structure. However, more an more, I'm preferring to use implicitly defined types.

It would be nice (makes my life easier) if a function return could be used as the Type reference of a @typedef.

Example

Code Example. Please excuse code quality.
/** @typedef {Coffee@returns} CaffeineDrink */

/**
 * @param {Boolean} cream
 * @param {Boolean} sugar
 * @returns {Drink}
 */
export default function Coffee(cream, sugar) {
  const self = {
    privateProperties: {
      coffeeMachine: () => {},
      makeCoffee: () => Math.random(),
    },
  };

  /** @typedef {drink} Drink */
  /**
   * @member
   */
  const drink = {
    isCold: self.privateProperties.makeCoffee() > 0.5,
    hasCream: cream,
    hasSugar: sugar,
  };

  self.drink = drink;

  return self.drink;
}

Benefits

In the example above, CaffeineDrink would be a type represented as an Object {isCold: boolean, hasCream: boolean, hasSugar: boolean}.

Modifying the return of Coffee, or more specifically the drink variable, would implicitly update the structure of CaffeineDrink.

Workaround

I am using VSCode, so this could possibly be a TypeScript/VSCode thing. But it works for me, and I'll convey it here.

Workaround Example
// I think this is a bug, to reference Coffee this way. See @typedef of 'Coffee' w/in the function
/** @typedef {Coffee} CaffeineDrink */

/**
 * @param {Boolean} cream
 * @param {Boolean} sugar
 * @returns {Coffee}
 */
export default function Coffee(cream, sugar) {
  const self = {
    privateProperties: {
      coffeeGrounds: {flavor: 'Pike\'s Peak'},
      coffeeMachine: () => {},
      makeCoffee: () => Math.random(),
    },
  };

  /**
   * I think this is a hacky/buggy way to specify the return type, using the function's name.
   * @typedef {drink} Coffee
   */
  /**
   * @member
   */
  const drink = {
    isCold: self.privateProperties.makeCoffee() > 0.5,
    hasCream: cream,
    hasSugar: sugar,
  };

  self.drink = drink;

  return self.drink;
}
Screenshot of Typehinting

image

The key points to make this workaround successful are

  1. Identifying the variable as a Member of the function
    • /**
       * @member
       */
      const drink = {}
      
  2. Creating a TypeDef who's name matches the parent function
    • /** @typedef {drink} Coffee */
      
  3. Finally, referencing the Function/TypeDef in a new TypeDef, for scope purposes.
    • /** @typedef {Coffee} CaffeineDrink */
      

shmolf avatar Mar 29 '21 02:03 shmolf

Hi, I'm also interested in this feature request, it would be neat!

mxmaxime avatar May 10 '22 08:05 mxmaxime