Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Documenting arrays in JSDoc typedefs for VS Intellisense

In my VS2015 JavaScript app, I have a JSON object that I get from a REST API that I have documented using JSDoc @typedef comments:

/**
 * @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
 */

When I reference this type in JSDoc comments on the methods that consume these JSON objects, I can get Intellisense documentation just fine:

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

However, I simply cannot get this to work with arrays - when I attempt to index the array, I get the "yellow triangles" menu that happens when VS can't get Intellisense context for you:

/**
 * @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's other recommended method, using {Array.<JSON_Response>}, informs VS that response is an Array but does not give Intellisense for anything under that. Microsoft's own XML comments do provide this capability, but only for function parameters - I can't reach inside the objects, nor would I like to do so because I'd have to add this documentation every time the function is called.

Is there any way to document arrays with their underlying types in JavaScript's VS Intellisense?

If I have to write code, I want to minimize the side effects / be able to factor it out of the release.

like image 983
TheHans255 Avatar asked Jan 18 '16 21:01

TheHans255


People also ask

What is the use of @type in JSDoc?

The @type tag allows you to provide a type expression identifying the type of value that a symbol may contain, or the type of value returned by a function. You can also include type expressions with many other JSDoc tags, such as the @param tag.

Do all of the JSDoc overloads share the same IntelliSense?

A cursory glance shows that each of the overloads above shares the same JSDoc. Each has the "Set the value..." from the API docs as the overarching Intellisense that is displayed for the Function setter. And each has the same @param func comment as well.

How does TypeScript support IntelliSense?

As the above screenshot demonstrates TypeScript supports Intellisense through a slightly tweaked implementation of JSDoc: With 0.8.2, the TypeScript compiler and tools now support JSDoc comments. In the TypeScript implementation, because types are already part of the system, we allow the JSDoc type annotation to be elided, as in the example above.

Why does Visual Studio not recognize JSDoc syntax?

Visual Studio will not recognize the JSDoc syntax you are using to define the type of element within your array—at least not where intellisense is concerned. XML is the solution here.


2 Answers

Okay, so I actually read your question this time (sorry, I was in the middle of something earlier).

Issue

Visual Studio will not recognize the JSDoc syntax you are using to define the type of element within your array—at least not where intellisense is concerned.

Solution

XML is the solution here. You may be aware of this, but you can use JSDoc tags in conjunction with XML comments to circumvent their individual limitations. I'm not sure what tags and attributes you were using when you ran your tests earlier, but here is the correct implementation of your code:

/**
 * @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
}

DOCUMENTING NESTED PARAMETER PROPERTIES FOR INTELLISENSE

Regarding your comment and the edits you made to your question, you can specify nested property types of parameters using the value attribute of the param XML comment. The term "value" is a little misleading, because according to the MSDN documentation, it isn't used to actually specify a value but rather a value type. See below:

/**
 * @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
}

Regarding Companynerd225's alternate solution

I'm not entirely sure that categorizing JSON objects as classes instead of types is the most accurate method here. Also, although I may not know the proper terms for it, I'm pretty sure a function returning {id:0} is not the same as a function returning this. See below:

Class vs. Objects

Not to mention, you would end up filling your JSDoc "Classes" section with types. By default, it would look like this in your navigation:

Malformed JSDoc Classes Section


like image 88
Ross Brasseaux Avatar answered Oct 25 '22 06:10

Ross Brasseaux


It seems counter-intuitive, but the best way to get documentation on your JSON types, rather than bothering with the limitations of XML comments and Intellisense's limited ability to parse JSDoc, is to actually write constructors that produce your types, then reference it so that it is only parsed for documentation purposes.

In other words, have constructors in your JavaScript that look like this:

/**
 * @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"
  }
}

You don't necessarily need all of the individual object types defined out: you can use whatever you'd like. You can even copy and paste a sample of your JSON output. You only need to divide out classes if you intend to store inner objects in other variables.

And then, instead of actually including the JavaScript file in your page, you can put all of these JSON constructors in a separate file and put an XML reference directive

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

at the top of your consuming JavaScript files - Visual Studio will run the code for the sole purpose of providing documentation.

like image 27
TheHans255 Avatar answered Oct 25 '22 06:10

TheHans255