最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - JSDoc Include All Properties from Another @typedef Object - Stack Overflow

programmeradmin4浏览0评论

If I use JSDoc to create two objects, one of which has all of the properties of the other, how do I show that?

For instance you'd have:

/** 
 * @typdef Foo
 * @type {Object}
 * @property {string} bar
 * @property {string} baz
 */

/**
 * @typedef Foobar
 * @type {Object}
 * @property {float} value
 * @property {string} bar
 * @property {string} baz
 */

But I'd like to not have to write out bar/baz twice I'd like to just inherit it.

If I use JSDoc to create two objects, one of which has all of the properties of the other, how do I show that?

For instance you'd have:

/** 
 * @typdef Foo
 * @type {Object}
 * @property {string} bar
 * @property {string} baz
 */

/**
 * @typedef Foobar
 * @type {Object}
 * @property {float} value
 * @property {string} bar
 * @property {string} baz
 */

But I'd like to not have to write out bar/baz twice I'd like to just inherit it.

Share Improve this question asked Feb 8, 2017 at 21:32 user3591723user3591723 1,2841 gold badge10 silver badges23 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 7

I believe you'd do this...

/** Type definition for Foo.
 * @typedef {Object} Foo
 * @property {string} bar
 * @property {string} baz
 */

/** Type definition for Foobar.
 * @typedef {Foo} Foobar
 * @property {float} value
 */

Notice how Foobar is "inheriting" from Foo.

This works in VSCode, not sure how ideal it is.

/**
 * @typedef {Object} Person
 * @property {string} firstName
 * @property {string} lastName
 * @property {number} age
 */

/**
 * @typedef {Object} BaseUser
 * @property {string} username
 */

/**
 * @typedef {Person & BaseUser} User
 */

User now has intellisense on all properties of Person and BaseUser

You can make a simple jsdoc plugin to make it so you can use @augments/@extends on a typedef. For instance, such a plugin can be found here (and shown below):

/**
 * Define a jsdoc plugin to update typedefs that use augments.
 */
exports.handlers = {
  /**
   * Modify typedefs that use augments (extends).  Add the base typedef's
   * properties to the augmented typedefs.
   */
  parseComplete: function (e) {
    var typedefs = {},
        augmentedTypedefs = {},
        numAugmented = 0;
    /* Make a dictionary of all known typedefs and a dictionary of augmented
     * typedefs */
    e.doclets.forEach(function (doclet) {
      if (doclet.kind === 'typedef') {
        typedefs[doclet.longname] = doclet;
        if (doclet.augments && doclet.augments.length) {
          augmentedTypedefs[doclet.longname] = doclet;
        }
      }
    });
    while (Object.keys(augmentedTypedefs).length !== numAugmented) {
      numAugmented = Object.keys(augmentedTypedefs).length;
      Object.keys(augmentedTypedefs).forEach(function (name) {
        var doclet = augmentedTypedefs[name];
        /* If this typedef is augmented by an augmented typedef, skip it for
         * now.  Ignore self references */
        if (doclet.augments.some(function (augmentName) {
          return augmentName !== name && augmentedTypedefs[augmentName];
        })) {
          return;
        }
        /* Ensure we have properties */
        doclet.properties = doclet.properties || [];
        /* Make a dictionary so we don't clobber known properties. */
        var properties = {};
        doclet.properties.forEach(function (prop) {
          properties[prop.name] = prop;
        });
        /* For each augment base, add its properties if we don't already have
         * them.  If the typedef augments two other typedefs that each have a
         * property of the same name, the last listed will be shown (done by
         * reversing the augments list). */
        doclet.augments.slice().reverse().forEach(function (augmentName) {
          if (augmentName !== name && typedefs[augmentName] && typedefs[augmentName].properties) {
            typedefs[augmentName].properties.forEach(function (prop) {
              if (!properties[prop.name]) {
                /* Make a copy so we don't mutate the original property. */
                prop = Object.assign(prop);
                /* Add a value that a rendering template could use to show that
                 * the property was inherted from a parent.  Since that in turn
                 * could have been inherited, preserve a known value. */
                prop.inherited = prop.inherited || augmentName;
                /* Add the property to the typedef and to the list of known
                 * properties. */
                doclet.properties.push(prop);
                properties[prop.name] = prop;
              }
            });
          }
        });
        /* We've finished processing this typedef, so remove it from the
         * augmented list. */
        delete augmentedTypedefs[name];
      });
    }
  }
};

At which point, you can do:

/** 
 * @typdef Foo
 * @type {Object}
 * @property {string} bar
 * @property {string} baz
 */

/**
 * @typedef Foobar
 * @type {Object}
 * @augments Foo
 * @property {float} value
 */

You can modify your template to show the inherited properties differently from the non-inherited properties if you desire (see an example):

I found such a solution when I was solving a similar problem:

/**
 * @typedef { { id: number, name: string }} type_1
/** 

/**
 * @typedef { { value: number} } type_2
/** 

/** 
 * @typedef { type_1 & type_2 } bination_of_1_and_2
*/
发布评论

评论列表(0)

  1. 暂无评论