I have a JavaScript function getting some parameters including object types. However, one property of a parameter, which is an object, will be used as deprecated. I would like to indicate this situation in the documentation, however I don't know how to use #param tag with #deprecated. Consider the example below:
/**
* This function does something.
*
* #name myFunction
* #function
* #since 3.0
* #param {function} [onSuccess] success callback
* #param {function} [onFailure] failure callback
* #param {object} [options] options for function
* #param {string} [options.lang] display language
* #param {string} [options.type] type of sth
*/
this.myFunction= function (onSuccess, onFailure, options) {
//do something
}
I want to deprecate "type" property of "options" object. How can I do that, or can I?
Official JSDoc documentation does not indicate that the #deprecated tag can be used for deprecating anything else than an entire symbol.
The #deprecated tag can be used to document that for example a function as a whole has been deprecated.
/**
* #deprecated since version 2.0.0
*/
function old () {
}
You can of course, as #Droogans said in the comments, add something like deprecated: in front of the #param description. If a developer somehow still ends up using the deprecated feature, you could implement a warning of some sorts.
/**
* #param {string=} bar - Deprecated: description
*/
function foo (bar) {
if (bar) {
console.warn('Parameter bar has been deprecated since 2.0.0')
}
}
A suggestion is using typescript, like so:
function test(
options: {
/**
* #deprecated use newName instead
*/
name?: string,
newName?: string
}) {
}
Related
For instance, I have the following function:
function createInstanceOf(ObjectConstructor) {
return new ObjectConstructor;
}
I want to make WebStorm autocompletion working when I pass a class as an argument. For example: if I call createInstanceOf(ClassA) I want to see autocompletion for ClassA instance, if I call createInstanceOf(ClassB) – for ClassB instance. So JSDoc function has to be generic.
It's easy to define a generic function with JSDoc and make #return value type be the same as #param, but I've found no way to treat #param type as a constructor for returned object.
So this doesn't work:
/**
* #param {T} ObjectConstructor
* #returns {T}
* #template T
*/
function createInstanceOf(ObjectConstructor) {
return new ObjectConstructor;
}
I also tried to make it working this way:
/**
* #param {function(new:T)} ObjectConstructor
* #returns {T}
* #template T
*/
function createInstanceOf(ObjectConstructor) {
return new ObjectConstructor;
}
But maybe I use closure types wrong, or WebStorm can't resolve such generic types.
If there're several solutions for JSDoc, I'd like to find out which ones work specifically with WebStorm IDE autocompletion.
Thank you
You probably don't need this anymore, but I too have been stuck on this for months so for other people wondering, you can do it like this:
/**
* #template T
* #param {new() => T} ObjectConstructor
* #returns {T}
*/
function createInstanceOf(ObjectConstructor) {
return new ObjectConstructor;
}
Got the answer from this article
I have several modules that all act the same way and export several functions inside of an object, like so:
module.exports = {
a:function(paramA,paramB) {
return 1;
},
b:function(paramC,paramD) {
return 'a';
}
}
They all follow the same schema (take these parameters, do things, and return this type). I'd like to be able to document all these files within the same file, so that documentation isn't repeated everywhere. The problem I'm running into is that if I create a #typedef with these functions specified, it is ignored if done like so:
/**
* #typedef {Object} myModuleType
* #property {functionType} a
*/
/**
* #module A
* #type {myModuleType}
*/
module.exports = {}
And if I create an interface, it complains that the methods are not implemented if done like so:
/**
* #interface myModuleType
*/
/**
* #function
* #name myModuleType#a
* #param paramA
* #param paramB
* #return {number}
*/
/**
* #module A
* #implements {myModuleType}
*/
module.exports = {}
Any ideas on how to get this to work?
So the original #type annotation actually works, it just doesn't autocomplete as it should in WebStorm after being documented.
This is being tracked at YouTrack for WebStorm as to when it will be fixed.
Edit: As of 12/18/2017, this has been fixed in a recent build of WebStorm and should hit the main branch soon.
I'm trying to document the input parameters to a function in javascript, but I can't work out how to do it in jsdoc.
I've looked at the jsdoc documentation which suggests that using the #callback comment is what's required, but Visual Studio Code (vscode) doesn't highlight it as per the screenshot.
The intellisense for the location parameter shows that it's type any rather than of type locator (a function with a parameter of id which returns a Location).
Example code which shows a function calling a function passed as a parameter:
class Location {
constructor(position, count) {
this.position = position;
this.count = count;
}
}
const items = {
'USB Cable': new Location('Desk Drawer', 123),
Keyboard: new Location('Desk Surface', 1),
};
/**
* A locater.
* #param {string} id
* #returns {Location}
*/
const locaterA = id => items[id];
/**
* Finds the item by its unique id.
* #callback locater
* #param {string} id
* #returns {Location}
*/
/**
* Attempt to find the item with the given locater.
* #param {string} id
* #param {locater} locater
*/
const locate = (id, locater) => locater(id);
const result = locate('USB Cable', locaterA);
console.log(result);
Is this a problem with what I'm doing, vsdoc not supporting the use case, or vscode not supporting it?
Edit: vscode seems to be supporting #callback starting from TypeScript 2.9
Vscode's IntelliSense doesn't support #callback. It's being tracked here: https://github.com/Microsoft/TypeScript/issues/7515.
As a convenient workaround you can use #typedef:
/**
* Finds the item by its unique id.
* #typedef {function(string): Location} Locater
*/
/**
* Attempt to find the item with the given locater.
* #param {string} id
* #param {Locater} locater
*/
const locate = (id, locater) => locater(id);
It looks like you're using it correctly, per JSDoc itself. However, it looks like Visual Studio may only support a limited subset of JSDoc, which doesn't include #callback: https://msdn.microsoft.com/en-us/library/mt162307.aspx
I don't have Visual Studio handy, but you might try the Google Closure style, which is to do it like this:
#param { function(string) : number } locator
This says that it's a function that takes a string, and returns a number.
You can find that documentation here: https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler (search for "Function Return Type" to jump to the relevant section).
I've noticed with JetBrains stuff at least, that it supports that syntax.
Since I was sent here from reddit concerning the documentation of an async function passed to another func, I answer here even if it's not exactly the op's question.
It's enough to document the return of the function with a Promise, in ES6 :
/**
* #param {(input: any) => Promise<any>} asyncFunctionAsParam - async function given
*/
const myfunc = (asyncFunctionAsParam) => {
// ...
}
How can I refer to a complex function type with the Google closure compiler and not an instance of the constructor function?
externs.js - Externs for CoolLibrary.matchSomething
/** #externs */
/** #const */
const CoolLibrary = {};
/**
* #param {!Object} object The object to inspect.
* #param {!Object} source The object of property values to match.
* #param {!function(!Object): !Object} customizer The function to customize
* comparisons.
* #return {boolean} Returns `true` if `object` is a match, else `false`.
* #constructor
*/
CoolLibrary.matchSomething = function(object, source, customizer) {};
/**
* #param {string} src
* #return {!Object}
*/
function require(src) {}
foo.js - application code
goog.module('foo');
const isMatchWith = /** #type {!CoolLibrary.matchSomething} */ (require('coollibrary.matchsomething'));
const foo = isMatchWith({}, {}, (val) => {});
I'm invoking it like so:
java -jar closure-compiler-v20161201.jar --js=foo.js --externs=externs.js --new_type_inf
Here's a runnable version at the Closure Compiler Debugger
It errors with:
foo.js:3: WARNING - Bad type annotation. Unknown type Lodash.isMatchWith
const isMatchWith = /** #type {!Lodash.isMatchWith} */ (require('lodash.ismatchwith'));
^
0 error(s), 1 warning(s), 72.7% typed
It works if I use #typedef but that loses most of the information. Is there a better way to add type information than using typedef like below?
/** #typedef {function(!Object, !Object, function(!Object):!Object):boolean} */
CoolLibrary.matchSomething;
Function definitions are not type names. You can use a typedef to prevent retyping this data if you import the function it in multiple places. However, if you only import the information in a single place, then a typedef would be overkill.
For a single import, you would simply duplicate the function annotation in the type cast at your require call.
const isMatchWith =
/** #type {function(!Object, !Object, function(!Object):!Object):boolean} */
(require('lodash.ismatchwith'));
The compiler handles these cases for you when module bundling is used, but that requires all of the source files to be compatible with the compiler and provided as part of the compilation. This is not currently possible for an external library.
Edit: This is technically a 2 part question. I've chosen the best answer that covers the question in general and linked to the answer that handles the specific question.
What is the best way to document anonymous objects and functions with jsdoc?
/**
* #class {Page} Page Class specification
*/
var Page = function() {
/**
* Get a page from the server
* #param {PageRequest} pageRequest Info on the page you want to request
* #param {function} callback Function executed when page is retrieved
*/
this.getPage = function(pageRequest, callback) {
};
};
Neither the PageRequest object or the callback exist in code. They will be provided to getPage() at runtime. But I would like to be able to define what the object and function are.
I can get away with creating the PageRequest object to document that:
/**
* #namespace {PageRequest} Object specification
* #property {String} pageId ID of the page you want.
* #property {String} pageName Name of the page you want.
*/
var PageRequest = {
pageId : null,
pageName : null
};
And that's fine (though I'm open to better ways to do this).
What is the best way to document the callback function? I want to make it know in the document that, for example, the callback function is in the form of:
callback: function({PageResponse} pageResponse, {PageRequestStatus} pageRequestStatus)
Any ideas how to do this?
You can document stuff that doesnt exist in the code by using the #name tag.
/**
* Description of the function
* #name IDontReallyExist
* #function
* #param {String} someParameter Description
*/
/**
* The CallAgain method calls the provided function twice
* #param {IDontReallyExist} func The function to call twice
*/
exports.CallAgain = function(func) { func(); func(); }
Here is the #name tag documentation. You might find name paths useful too.
You can use #callback or #typedef.
/**
* #callback arrayCallback
* #param {object} element - Value of array element
* #param {number} index - Index of array element
* #param {Array} array - Array itself
*/
/**
* #param {arrayCallback} callback - function applied against elements
* #return {Array} with elements transformed by callback
*/
Array.prototype.map = function(callback) { ... }
To compliment studgeek's answer, I've provided an example that shows what JsDoc with Google Closure Compiler lets you do.
Note that the documented anonymous types get removed from the generated minified file and the compiler ensures valid objects are passed in (when possible). However, even if you don't use the compiler, it can help the next developer and tools like WebStorm (IntelliJ) understand it and give you code completion.
// This defines an named type that you don't need much besides its name in the code
// Look at the definition of Page#getPage which illustrates defining a type inline
/** #typedef { pageId : string, pageName : string, contents: string} */
var PageResponse;
/**
* #class {Page} Page Class specification
*/
var Page = function() {
/**
* Get a page from the server
* #param {PageRequest} pageRequest Info on the page you want to request
*
* The type for the second parameter for the function below is defined inline
*
* #param {function(PageResponse, {statusCode: number, statusMsg: string})} callback
* Function executed when page is retrieved
*/
this.getPage = function(pageRequest, callback) {
};
};
#link can add inline links to methods and classes.
/**
* Get a page from the server
* #param {PageRequest} pageRequest Info on the page you want to request
* #param {function} callback Function executed when page is retrieved<br />
* function({#link PageResponse} pageResponse,{#link PageRequestStatus} pageRequestStatus)
*/
this.getPage = function (pageRequest, callback) {
};
Not ideal, but it gets the job done.
The Google Closure Compiler Annotations has Type Expressions for this which includes the ability to indicate type for specific arguments, return type, and even this. Many libraries are looking at following the Google Closure Compiler Annotations, because they want to use it to shrink their code. So it's got some momentum. The downside is I don't see a way to give the description.
For providing the description perhaps the JSDoc Toolkit Parameters With Properties approach would work (look at the bottom of the page). It's what I am doing right now. The JSDoc Toolkit is prepping to start work on V3, so feedback there might be good.
You could use #see to link to another method within the same class. The method would never be used, it would just be there for documentation purposes.
/**
* #class {Page} Page Class specification
*/
var Page = function() {
/**
* Get a page from the server
* #param {PageRequest} pageRequest Info on the page you want to request
* #param {function} callback Function executed when page is retrieved
* #see #getPageCallback
*/
this.getPage = function (pageRequest, callback) {
};
/**
* Called when page request completes
* #param {PageResponse} pageResponse The requested page
* #param {PageRequestStatus} pageRequestStatus Status of the page
*/
//#ifdef 0
this.getPageCallback = function (pageResponse, pageRequestStatus) { };
//#endif
};
If you are using some kind of build system, the dummy method could easily be omitted from the build.
hope I'm not too late on this topic, but you can do something like this
/**
* Get a page from the server
* #param {PageRequest} pageRequest
* #param {(pageResponse: PageResponse, pageRequestStatus: PageRequestStatus) => void} callback
*/
this.getPage = function(pageRequest, callback) {}
the downside of this approach is that you can't document what each of the arguments does.