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 badges4 Answers
Reset to default 7I 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
*/