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.
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.
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.
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.
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.
Okay, so I actually read your question this time (sorry, I was in the middle of something earlier).
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. 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
}
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
}
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:
Not to mention, you would end up filling your JSDoc "Classes" section with types. By default, it would look like this in your navigation:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With