在 VS Intellisense 的 JSDoc 类型定义中记录数组

Posted

技术标签:

【中文标题】在 VS Intellisense 的 JSDoc 类型定义中记录数组【英文标题】:Documenting arrays in JSDoc typedefs for VS Intellisense 【发布时间】:2016-04-24 04:19:18 【问题描述】:

在我的 VS2015 javascript 应用程序中,我有一个从 REST API 获得的 JSON 对象,我使用 JSDoc @typedef cmets 记录了该对象:

/**
 * @typedef Object JSON_Response
 * @property Number id
 * @property String name
 * @property JSON_Response_Tag tag
 */

/**
 * @typedef Object JSON_Response_Tag
 * @property Number id
 * @property String color
 */

当我在 JSDoc cmets 中在使用这些 JSON 对象的方法上引用此类型时,我可以很好地获得 Intellisense 文档:

/**
 * @param JSON_Response response
 */
function process_response(response) 
  // process response here...

但是,我根本无法让它与数组一起使用 - 当我尝试索引数组时,当 VS 无法为您获取 Intellisense 上下文时,我会看到“黄色三角形”菜单:

/**
 * @typedef Object JSON_Response
 * @property Number id
 * @property String name
 * @property JSON_Response_Tag[] tags
 */

/**
 * @param JSON_Response response
 */
function process_response(response) 
  response.tags[0]. // no intellisense here

JSDoc 的其他推荐方法,使​​用Array.<JSON_Response>,通知 VS response 是一个数组,但不提供智能感知。 Microsoft 自己的 XML cmets 确实提供了这种功能,但仅限于函数参数 - 我无法进入对象内部,我也不想这样做,因为每次调用函数时我都必须添加此文档。

有没有办法在 JavaScript 的 VS Intellisense 中记录数组及其底层类型?

如果我必须编写代码,我想尽量减少副作用/能够将其排除在发布之外。

【问题讨论】:

【参考方案1】:

好的,这次我真的读到了你的问题(抱歉,我之前在做某事)。

问题

Visual Studio 无法识别您用来定义数组中元素类型的 JSDoc 语法——至少在涉及智能感知的情况下不会。

解决方案

XML 是这里的解决方案。您可能知道这一点,但是您可以将 JSDoc 标记与 XML cmets 结合使用来规避它们各自的限制。我不确定您之前运行测试时使用的标签和属性,但这里是您的代码的正确实现:

/**
 * @typedef Object JSON_Response
 * @property Number id
 * @property String name
 * @property JSON_Response_Tag tag
 */

/**
 * @typedef Object JSON_Response_Tag
 * @property Number id
 * @property String color
 */

/**
 * @param JSON_Response[] response
 */
function process_response(response) 
    /// <param name='response' type='Array' elementType='JSON_Response'></param>

   response[0]. // intellisense works here


为 INTELLISENSE 记录嵌套参数属性

关于您的评论和您对问题所做的编辑,您可以使用param XML 评论的value 属性指定参数的嵌套属性类型。术语“值”有点误导,因为根据MSDN documentation,它不用于实际指定值,而是用于指定值type。见下文:

/**
 * @typedef Object JSON_Response
 * @property Number id
 * @property String name
 * @property JSON_Response_Tag[] tag
 */

/**
 * @typedef Object JSON_Response_Tag
 * @property Number id
 * @property String color
 */

/// <summary name='JSON_Response_Tag' type='Object'>my test summary</summary>
/// <field name='id' type='Number'>testid</field>
/// <field name='color' type='String'>testcolor</field>

/**
 * @param JSON_Response response
 */
function process_response(response) 
    /// <param name='response' type='JSON_Response' value='id:0,name:"",tag:[id:0,color:""]'></param>

    response.tag[0]. // intellisense works here


关于 Companynerd225 的替代解决方案

我不完全确定将 JSON 对象分类为类而不是类型是这里最准确的方法。此外,虽然我可能不知道它的正确术语,但我很确定返回 id:0 的函数与返回 this 的函数不同。见下文:

更不用说,你最终会用类型填充你的 JSDoc“类”部分。默认情况下,它在您的导航中看起来像这样:


【讨论】:

对不起,但这并不能回答我的问题。这些是我没有在代码中定义的故意伪造的类型。问题是我需要能够访问这些类型的数组而不是单个实例。 @Compynerd255 查看我修改后的答案。那里的代码适用于文档生成和准确的智能感知。 好的,这更有意义。不过,我意识到我需要编辑我的问题:问题是数组在 inside JSON 对象中,XML 注释无法触及。 谢谢。这确实有效,但它需要在数据的每个消费者内部复制知识。我实际上找到了解决这个问题的更好方法(作为答案发布)。【参考方案2】:

这似乎违反直觉,但最好的方法是获取有关 JSON 类型的文档,而不是为 XML cmets 的限制和 Intellisense 解析 JSDoc 的能力有限而烦恼,实际上编写生成您的类型的构造函数,然后引用它,以便仅出于文档目的对其进行解析。

换句话说,您的 JavaScript 中的构造函数如下所示:

/**
 * @constructor Object JSON_Response
 * @property Number id
 * @property String name
 * @property JSON_Response_Tag[] tags
 */
function JSON_Response()
  return 
    id: 0,
    name: "",
    tags: [new JSON_Reponse_Tag()]
  


/**
 * @constructor Object JSON_Response_Tag
 * @property Number id
 * @property String color
 */
function JSON_Response_Tag()
  return 
    id: 0,
    color: "#000000"
  

您不一定需要定义所有单独的对象类型:您可以使用任何您喜欢的对象类型。您甚至可以复制和粘贴 JSON 输出的示例。如果您打算将内部对象存储在其他变量中,则只需要划分类。

然后,您可以将所有这些 JSON 构造函数放在一个单独的文件中,并放置一个 XML 引用指令,而不是实际将 JavaScript 文件包含在您的页面中

/// <reference path="~/path/to/schema_file.js" />

在您使用的 JavaScript 文件的顶部 - Visual Studio 将运行代码,其唯一目的是提供文档。

【讨论】:

您可能已经解决了这些问题,但我在这里看到了一些问题。我假设您会从 JSDoc 命令中省略方案文件?否则,您最终会在 JSDoc 文档中得到一堆类而不是类型。我现在看到的所有其他问题都源于此。例如,如何在不复制代码的情况下正确维护文档的 typedef,同时维护智能感知的构造函数? 这些替换了 typedef。由于 JSON 总是返回一个对象作为根,这些类型总是类。 我还在学习,但你的那些函数不会返回对象文字,而不是类吗?它们是 typedef 的用途,不是吗?您必须返回“this”才能让它们成为类。它们没有实例,因为它们都返回相同的新创建对象。假设我说它们不是类是正确的,那么你不会用应该是什么类型来污染你的“类”部分吗? 当您从使用new 调用的函数返回对象时,它会覆盖“使用函数原型创建新对象并将其绑定到this”行为,只需将该对象提供给调用者(并允许this 超出范围)。从任何意义上来说,它仍然是一个构造函数,JSDoc 和 VS Intellisense 就是这样记录的,将有限的信息外推到完整的类型。这些是真正的对象类,就像允许构造函数返回 this 产生一个类一样。 我可能不知道如何充分描述返回 this 的函数和返回对象的函数之间的区别,但我很确定它们是不同的。我在上面的回答中添加了一些担忧。

以上是关于在 VS Intellisense 的 JSDoc 类型定义中记录数组的主要内容,如果未能解决你的问题,请参考以下文章

基于VS Code的JSDoc的使用指南

VS code 整合JsDoc

我的 VS2017 Intellisense 发生了啥

Intellisense 提示和 XML 返回注释 (VS2008)

在VS2008中使用Qt时,IntelliSense无法正常工作

在VS2008中我应该对jquery有多少intellisense?