Javascript: Move JSDoc's outside of code - javascript

I ask this mostly from a Angular perspective (but any advice would help). I have JSDoc's on my functions but it makes the code look very messy. I would just like to know if there is a way to move the JSDoc's to some type of external file.
An example of my JSDoc's:
/**
* Does a GET call on the service MyGetCall
* #param {string} pUserID - 1st Parameter: User Login ID
* #param {string} pPassword - 2nd Parameter: User Password
* #returns The Call's Http Observable (subscribe to this function).
* #example this.flowservice.MyGetCall('Johnny', 'MySuperSecretPassword')
* .subscribe(response => {
* console.log(response)
* });
*/
MyGetCall(pUserID: string, pPassword: string): Observable<any> {
const temp = this.httpclient.get<JSON>(`http://XXX/MyGetCall?userid=${pUserID}&password=${pPassword}`, {headers: this.headers});
return temp;
}
So in this example I would like to remove all the JSDoc's and put it in some kind of external file (jsdocs.xxx). This file would then look something like this:
MyGetCall:
/**
* Does a GET call on the service MyGetCall
* #param {string} pUserID - 1st Parameter: User Login ID
* #param {string} pPassword - 2nd Parameter: User Password
* #returns The Call's Http Observable (subscribe to this function).
* #example this.flowservice.MyGetCall('Johnny', 'MySuperSecretPassword')
* .subscribe(response => {
* console.log(response)
* });
*/
MyOtherFunction:
...
MyOtherOtherFunction:
...
Then I can import this file (jsdocs.xxx) somewhere for it to work with my app. For anyone that has used JSDoc's I hope this makes sense.

If, inline, I would document a class method like so:
/**
* #class
* #alias fileReader
*/
function fileReader() {
/**
* Tells the caller if it can handle the given file by returning a boolean.
*
* #param {File} file A `File` object.
* #returns {boolean} `true` if this reader can read a file.
*/
this.canRead = function (file) {
...
};
}
Instead, I could document my method somewhere else:
/**
* #class
* #alias fileReader
*/
function fileReader() {
this.canRead = function (file) {
...
};
}
And the documentation could be in a different file, like so:
/**
* Tells the caller if it can handle the given file by returning a boolean.
*
* #function canRead
* #memberof fileReader
* #instance
* #param {File} file A `File` object.
* #returns {boolean} `true` if this reader can read a file.
*/
The #function parameter defines the name of the function if the jsdoc isn't immediately followed by an actual function. The #memberof tells it the parent class or namespace. The #instance says that it is a method that requires an instantiated class rather.
For your example, I'm guessing that the documentation would be
/**
* Does a GET call on the service MyGetCall
* #function MyGetCall
* #memberof flowservice
* #instance
* #param {string} pUserID - 1st Parameter: User Login ID
* #param {string} pPassword - 2nd Parameter: User Password
* #returns The Call's Http Observable (subscribe to this function).
* #example this.flowservice.MyGetCall('Johnny', 'MySuperSecretPassword')
* .subscribe(response => {
* console.log(response)
* });
*/

This answer is mostly catered to VS Code if you're hoping to get Intellisense to pick up your types.
I've had success with simply creating my types in a typedefs.js file and referencing the type by using the ts/vscode import(path/to/file).Foo tag.
JSDoc does not support this syntax out of the box, so I suggest also using jsdoc-tsimport-plugin in order to parse your docs.
Eg: typedef.js:
/**
* #typedef {Object} Foo
* #property {string} id
*/
/**
* #typedef {Object} Bar
* #property {string[]} things
*/
// having to export an empty object here is annoying,
// but required for vscode to pass on your types.
export {};
coolFunction.js
/**
* This function is super dope
* #param {import('../typedef').Foo} foo - a foo
* #return {import('../typedef').Bar} bar - an array of bars
*/
export function (foo) {
// do cool things
return bar;
}

Related

How to add a paramater to a function in a class with JSDoc

So let's set the table here.
I have a class called Command and in that class I have an object as the parameter with 3 properties (name, description, execute())
class Command {
/**
*
* #param {Object} opts
* #param {String} opts.name
* #param {String} opts.description
* #param {Function} opts.execute
*/
constructor(opts) {
this.name = opts.name;
this.description = opts.description;
this.execute = opts.execute;
}
}
The execute property is a function and I want to pass in another set of JSDoc line for the parameter in those function.
It should generally work like this
module.exports = {
name: "Hello!",
description: "----",
/**
* #param {Message} message
* #param {Client} client
* #param {Array} args
*/
execute(message, client, args) {},
};
Is it possible to do this, or do I have to switch over to TypeScript?
Thank you in advance
you can use typedef and property, but you need to write it on all files you use it, it's better if you use a tsconfig.json.
you dont need typescript all you need is a tsconfig.json, but ofcourse typescript would be better.
https://www.typescriptlang.org/docs/handbook/tsconfig-json.html
/**
* The complete Triforce, or one or more components of the Triforce.
* #typedef {Object} WishGranter~Triforce
* #property {boolean} hasCourage - Indicates whether the Courage component is present.
* #property {boolean} hasPower - Indicates whether the Power component is present.
* #property {boolean} hasWisdom - Indicates whether the Wisdom component is present.
*/
/**
* A class for granting wishes, powered by the Triforce.
* #class
* #param {...WishGranter~Triforce} triforce - One to three {#link WishGranter~Triforce} objects
* containing all three components of the Triforce.
*/
function WishGranter(triforce) {}

Make JSDoc comment for function which takes another function as parameter

Imagine a function which accepts an "onUpdate" function as a parameter:
/**
* #param {function} onUpdate
* #returns {null}
*/
static async init(onUpdate) {
...
onUpdate(true);
};
onUpdate takes a boolean as an argument.
I want to add that arguments to #param {function} onUpdate.
Is there a way?
Some magnificent devs managed to do it on these addEventListener functions:
I think in screenshot you see typescript hint. But you can do something like this:
/**
* This callback is displayed as a global member.
* #callback someCallback
* #param {number} param1
* #param {number} param2
* #returns {number}
*/
/**
*
* #param {someCallback} cb
*/
function someFunction(cb) {
}
And see this hint

JSDoc - How to document methods of a prototype object

Based on my understanding of the naming inheritence in JSDoc, this should work defining #name User.format#name but it does not
/**
* #class
* #classdesc Stores the logged in user's information. Handles user updates and includes helper
* methods for formatting users
*/
User = function() {};
/**
* Object containing utility methods for formatting user objects
*
* #name User.format
* #property {object}
*/
User.prototype.format = {
/**
* returns the full name of a user
*
* #name User.format#name
* #param {User} user
* #returns {string} the full name
*/
name: function(user) {
// some utility function
}
};

How to define a function to be a callback implementation in JSDoc?

I defined a #callback that way :
/**
* #callback MyClass~Handler
* #param {string} target
* #param {Options} options - Original options
*/
I use it to define my class prototype :
/**
* #param {string} name - The name
* #param {MyClass~Handler} handler
* #private
*/
MyClass.prototype._builder = function(name, handler) { //...
But how to tell JSDoc that the following function has the same definition as my MyClass~Handler (something that would be like #isacallback in the following code)?
/**
* Default handler
* #isacallback {MyClass-Handler}
* #private
*/
MyClass.prototype._defaultHandler = function(target, options) { // ...
I haven't tested this, but since #callback just defines a type, couldn't you use the #type declaration?
In other words:
/**
* Default handler
* #type {MyClass-Handler}
* #private
*/
MyClass.prototype._defaultHandler = function(target, options) { // ...
See http://usejsdoc.org/tags-type.html for further info on #type.

Adding sub-properties to an existing property-list in jsdoc

I am trying to automate a particular module in our JS library and am stuck at a point where I want to define a set of properties (lets say an object that goes as construction parameter of a class).
/**
* This function initiates world peace!
* #constructor
* #param {object} defaults - The options to initiate peace.
* #param {number} defaults.issues - The number of issues being taken up.
* #param {string} defaults.source - The name of the location where process starts.
*/
var WorldPeace = function (defaults) {
// code here
};
It is well and good had all properties of the construction was defined at one location. Unfortunately, my code has a number of modules contributing to that construction properties. Lets say, at some other portion of the code (in a later file) causes to have a couple of more properties
* #param {Date} defaults.start - The date when the process started.
* #param {Date} defaults.stop - The date when the process should stop.
How do I go about adding to the original set of properties that I had previously defined for WorldPeace function? Doing something like a mixin or subclassing the properties would be going overboard! As such, if I can simply inject to a property list definition it would be great.
The easiest method is to use a record type:
/**
* This function initiates world peace!
* #constructor
* #param {{issues: number, source: string}} defaults - options to initiate peace.
*/
var WorldPeace = function (defaults) {
// code here
};
You could also implement an interface:
/** #interface */
var WordPeaceDefaults;
/** #type {number} */
WorldPeaceDefaults.prototype.issues;
/** #type {string} */
WorldPeaceDefaults.prototype.source;
/**
* This function initiates world peace!
* #constructor
* #param {WorldPeaceDefaults} defaults - options to initiate peace.
*/
var WorldPeace = function (defaults) {
// code here
};
/**
* #constructor
* #implements {WorldPeaceDefaults}
*/
function MyWorldPeaceDefaults() {}
/** #type {number} */
MyWorldPeaceDefaults.prototype.issues = 0;
/** #type {string} */
MyWorldPeaceDefaults.prototype.source = '';
WordPeace(new MyWorldPeaceDefaults);
Another way to do it would be to use a typedef:
/**
* #typedef {{
* issues: number,
* source: string
* }}
*/
var WorldPeaceOptions;
/**
* #constructor
* #param {WorldPeaceOptions} defaults
*/
var WorldPeace = function (defaults) {
// code here
};

Categories