如何在JSDOC中扩展typedef参数?

65
假设您在ES6类(文档)中有以下代码:

假设你在 ES6 类中有以下代码(文档):

/**
 * @typedef Test~options
 * @type {object.<string>}
 * @property {array} elements - An array containing elements
 * @property {number} length - The array length
 */

/**
 * @param  {Test~options} opt - Option object
 */
test(opt){

}

现在我想要记录另一个函数,我们称其为test2。该函数接收与options对象完全相同的参数,但需要另一个属性parent

如何记录此函数而不记录冗余的选项?冗余意味着:

/**
 * @typedef Test~options
 * @type {object.<string>}
 * @property {array} elements - An array containing elements
 * @property {number} length - The array length
 */

/**
 * @param  {Test~options} opt - Option object
 */
test(opt){

}


/**
 * @typedef Test~options2
 * @type {object.<string>}
 * @property {array} elements - An array containing elements
 * @property {number} length - The array length
 * @property {object} parent - The parent element
 */

/**
 * @param  {Test~options2} opt - Option object
 */
 test2(opt){

 }

1
在GitHub上的参考资料:https://github.com/jsdoc3/jsdoc/issues/1199 - dude
3个回答

67

我找到了这个解决方案,对我来说非常有效。 最初来自这里

 /**
 * @typedef {Object} ChildType
 * @property {String} childProp
 *
 * @typedef {Base & ChildType} Child
 */

更新:您也可以使用@extends来扩展 jsdoc typedef。

/**
 * @typedef {object} ChildType
 * @extends Base
 * @property {string} childProp
 */

第二种解决方案更好,因为在普通的jsdocs中不支持Base & ChildType


我实在无法理解第一个解决方案在做什么。这个解决方案非常清晰简明。 - Jared Beach
3
它被称为“交叉类型(intersection type)”。您可以点击链接了解更多信息。 - shaedrich
13
交叉类型是Typescript中的一种类型,但在普通JSDoc中不被支持。人们经常混淆官方支持的JSDoc语法和Typescript对JSDoc解析的实现。我怀疑这是因为Typescript驱动了VSCode的Intellisense,该功能在市场上有相当大的份额,甚至包括那些实际上并没有编写Typescript的人。 - Coderer
4
@Coderer:非常正确,但是由于 JSDoc 没有得到很好的维护(至少多年来没有扩展语言功能),我认为 TypeScript 的 JSDoc 风格现在真正成为了标准,不仅因为它被广泛采用,而且还因为它是唯一支持通过 import() 自动发现第三方模块的候选者。顺便说一下,我们计划将默认模式切换到 TypeScript 模式,即使是纯 JavaScript 用户(tsc 可以处理)也是如此,更多原因请参见 https://github.com/gajus/eslint-plugin-jsdoc/issues/834。 - Brett Zamir
1
我想知道最后一段代码是否适用于智能感知功能。在VSCode中进行了测试后,它坚持认为如果没有将@extends@class链接起来,就不能使用它 - 它显示了一个错误:_JSDoc '@extends' is not attached to a class._。在Webstorm中,我没有看到错误,但也没有显示基本类型的属性。 - Diego Bevilaqua
显示剩余3条评论

16

试一试

/**
 * @typedef {object.<string>} Test~options
 * @property {array} elements - An array containing elements
 * @property {number} length - The array length
 */

/**
 * @param {Test~options} opt - Option object
 */
test(opt){

}

/**
 * @typedef {Test~options} Test~options2
 * @property {object} parent - The parent element
 */

/**
 * @param  {Test~options2} opt - Option object
 */
test2(opt){

}

2
这是目前最好的解决方案,因为它将Test~options2类型指定为Test~options,并链接到后者。但这并不理想,因为它没有重复其“扩展”类型的所有参数;它只列出了新参数。JSDoc 应该在此方面改进标记。 - chharvey
只是想在这里留个注,以防有用——我认为你在这里并不像看起来那样被强制继承——你可以有类似这样的东西:@typedef {Mixin1 & Mixin2} MyMix(但请注意,当你这样做时,我的编辑器好像不喜欢添加到混合中的其他属性)。 - Andrew
1
我尝试使用这种方法来扩展HTMLElement的属性,但没有成功。 - Ajit Kumar
Andrew,请看一下我在另一个答案中的评论——这个答案可以在“普通”JSDoc中不使用任何不支持的扩展语法而工作,其中交集运算符(&)没有意义。 - Coderer
再次,我想知道这个是否也适用于智能感知 - VSCode没有为parent属性显示任何自动完成,并且如果我将其写成一个对象类型为/** @type { Test~options2 } */的属性,智能感知会告诉我它不被认为是该类型的已知属性(尽管在Jetbrains智能感知中似乎工作正常)。 - Diego Bevilaqua

9

我不喜欢没有“完整设置”的半吊子回答,所以这里提供一个:

/**
 * @typedef {Object} Person
 * @property {string} name - The person's name
 * @property {number} age - The person's age
 */
/**
 * @typedef {Object} WizardProperties
 * @property {string[]} magicPowers
 * @typedef {Person & WizardProperties} Wizard
 */
/** @type {Wizard} */
export const wizard = {
    name: "Harry",
    age: 20,
    magicPowers: ["brroooomm"]
}

它也适用于多个文件,但您必须使用 import('./person').Person 样式:

  • person.mjs:
/**
 * @typedef {Object} Person
 * @property {string} name - The person's name
 * @property {number} age - The person's age
 */
  • wizard.mjs:
/**
 * @typedef {Object} WizardProperties
 * @property {string[]} magicPowers
 * @typedef {import('./person').Person & WizardProperties} Wizard
 */
/** @type {Wizard} */
export const wizard = {
  name: "Harry",
  age: 20,
  magicPowers: ["brroooomm", "wheeeeeeeeeeeew"]
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接