I'm trying to use JSDoc to document the destructured parts of my react state hooks for example:
const [referenceState, setReferenceState] = useState(null);
Here, referenceState is of type Object, and setReferenceState expects an Object.
Based on some information online, I'm trying to do something along the lines of:
/**
* #param {Object} stateToSet
* #returns {GenericArray} current state and function to change value
*/
const [referenceState, setReferenceState] = useState(null);
But that doesn't generate anything..
Can someone please help me document referenceState and setReferenceState?
In webstorm, You can write like this (I haven't tested it in other editors):
const [state, setState] = useState(/** #type {{name: string, age: number?}} */null)
or
/**
* #typedef People
* #property {string} name
* #property {number} [age]
*/
//........
const [state, setState] = useState(/** #type {People} */null)
I think you can try this approach:
/**
* #typedef {Object} ReferenceState
*/
/**
* #callback ReferenceStateSetter
* #param {ReferenceState} state
* #returns {void}
*/
/**
* #namespace {Object}
* #property {ReferenceState} 0
* #property {ReferenceStateSetter} 1
*/
const [referenceState, setReferenceState] = useState(null);
Or, to avoid having to document the immediately destructured array, but benefiting from adding some indent changes at the end:
/**
* #typedef {Object} ReferenceState
*/
/**
* #callback ReferenceStateSetter
* #param {ReferenceState} state
* #returns {void}
*/
const [
/**
* #type {ReferenceState}
*/
referenceState,
/**
* #type {ReferenceStateSetter}
*/
setReferenceState
] = useState(null);
If you don't want to have documents for ReferenceState, you can get rid of its #typedef and replace references to it with Object, but I think it is clearer to have docs.
void above is a simpler way to say nothing special (i.e., undefined) is returned--if that's what the setter returns. Some projects would just drop the #returns if it only returns undefined, but I like to add it to show the return value is known to be undefined and not merely undocumented.
The shortest way is this: by adding a template
/**
* #type {[MyType, React.Dispatch<MyType>]} state
*/
const [value, setValue] = useState(null);
I also use *.d.ts files in the js projects. VS code sees them and uses them so you can describe types and interfaces in a modern way.
Just put a line
type useState<T> = [T, React.Dispatch<T>];
to a useState.d.ts file and then in a JS file use
/** #type {useState<MyType>} */
const [value, setValue] = useState(null);
I would create a generic type that equals the same return type as React's useState function.
/**
* Add this type in top of your file, or if commonly used in some types file.
* #template T
* #typedef {[T, import('react').Dispatch<import('react').SetStateAction<T>>]} useState
*/
Then you could use it in you React component like this:
/** #type {useState<string>} */
const [someString, setSomeString] = useState('');
/** #type {useState<number>} */
const [someNumber, setSomeNumber] = useState(2);
Or if you want to use a custom object:
/**
* #typedef SomeOtherType
* #property {string} property1
* #property {number} property2
*/
/** #type {useState<SomeOtherType>} */
const [someOtherValue, setSomeOtherValue] = useState(null);
As an alternative, the variables can be declared prior to destructuring and annotated with JSDoc as normal.
/**
* Current state.
* #type {Object}
*/
let referenceState;
/**
* Current state setter.
* #type {Function}
* #param {any} state updated state value.
* #returns void
*/
let setReferenceState;
[referenceState, setReferenceState] = useState(null);
Related
I am somewhat new to JSDoc, but I am trying to define a typedef that has a generically-typed function (the return type is inferred from the param type).
It seems like the following code should result in the type of the bar constant to be string. Instead I am getting an any type.
/**
* #template T
* #callback MyFunction
* #param {T} val
* #return {T}
*/
/**
* #typedef MyType
* #property {MyFunction} myFunction
*/
/** #type {MyType} */
const foo = {};
const bar = foo.myFunction('a string');
In your case, you should specify generic type for myFunction property:
/**
* #typedef MyType
* #property {MyFunction<string>} myFunction
*/
or you can make MyType generic too
/**
* #template T
* #typedef MyType
* #property {MyFunction<T>} myFunction
*/
but then you should specify generic type when define type for foo:
/** #type {MyType<string>} */
const foo = {};
const bar = foo.myFunction('a string');
// OR
/** #type {MyType<string|number>} */
const foo = {};
const bar = foo.myFunction('a string');
I'm adding type information for TypeScript to an existing JavaScript library via JSDoc. I have a constructor function that might set a property based on the value(s) of the parameter(s) it's given:
/**
* Settings you can use to configure an instance of an {#link ExampleClass}
*
* #typedef {Object} ExampleOptions
* #property {true} [option] You can set this to `true` to make a property on an instance of {#link ExampleClass} exist. If you don't set it, that property won't exist
*/
/**
* A thing that does stuff
*
* #constructor
* #param {ExampleOptions} [param] Options you can use to configure the new instance
*/
function ExampleClass(param) {
if(param.option === true) {
/**
* A property that only exists based on the options given to this constructor
*
* #type {boolean}
*/
this.property = true;
}
}
I was hoping that TypeScript would externally interpret the declaration of property to be like property?: boolean;, but it looks like it gets interpreted to be non-optional, and comes up in the autocomplete in my editor without having to check for its existence ahead of time. Ideally, I'd like for it to be an optional property that you'd have to check for before you can use it, or even allow you to use it unchecked if TypeScript can somehow guarantee that you had passed {option: true} to the constructor. How can I make that work?
Pre-declare the class with a #typedef with the optional properties and set it to the constructor as a variable of type {new () => ExampleClass}. This way it's even possible to declare this as the defined class and have code completion inside the constructor function itself. Something like the below:
/**
* Settings you can use to configure an instance of an {#link ExampleClass}
*
* #typedef {Object} ExampleOptions
* #property {true} [option] You can set this to `true` to make a property on an instance of {#link ExampleClass} exist. If you don't set it, that property won't exist
*/
/**
* #typedef {object} ExampleClass
* #prop {boolean} [property] A property that only exists based on the options given to this constructor
*/
/**
* A thing that does stuff
*
* #constructor
* #param {ExampleOptions} [param] Options you can use to configure the new instance
* #this {ExampleClass}
* #type {{new () => ExampleClass}}
*/
const ExampleClass = function (param) {
if(param.option === true) {
this.property = true;
}
}
Can you not just do
interface options {
option? : boolean;
}
/**
* A thing that does stuff
*
* #constructor
* #param {options} [param] Options you can use to configure the new instance
*/
function ExampleClass(param : options) {
if(param.option === true) {
/**
* A property that only exists based on the options given to this constructor
*
* #type {boolean}
*/
this.property = true;
}
}
I have a js file with a bunch of functions for modifying a user.
All the functions are documented with jsdoc making it easy to see what arguments to use and what the function does.
However I now want to extend every function with an optional context variable. So from this
/**
* creates a new user object
* #param {string} email
* #param {string} displayName
* #param {string} password
* #returns {User|Error}
*/
function newUser(email, displayName, password)
to this
/**
* creates a new user object
* #param {string} email
* #param {string} displayName
* #param {string} password
* #param {*} ctx
* #returns {User|Error}
*/
function newUser(email, displayName, password, ctx)
but since I have a lot of functions that would use the same ctx variable I thought that I could create a wrapper, like this
function withContext(ctx) {
/**
* #namespace
* #borrows newUser as new
*/
return {
new: (...args) => newUser(...args, ctx),
};
}
and it does work, in the sense that the right function seems to be called with the right arguments, but I can't seem to get IntelliSense to pick it up in vscode which has me thinking that I probably haven't written the jsdoc correctly.
according to vscode it says that the new function just takes an any[], which it of course does, but it is not what the documentation for newUser states, so am I doing something wrong with my documentation or is it simply not possible?
Seems like it is possible
/**
* #typedef {Object} UserService
* #property {newUser} newUser
*/
/**
* #returns {UserService}
*/
function withContext(ctx) {
return {
newUser: (...args) => newUser(...args, ctx),
};
}
that will "fix" IntelliSense and the documentation follows the function newUser that is previously defined
I'm trying to figure out how to comment it correctly using JSDoc3.
/**
* Module ...
*
* #module Cookie
* #returns {{create, get, remove}}
*/
const cookie = (function () {
/**
* Function to create cookie.
*
* #param {String} name - The cookie name.
* #param {String} value - The cookie value.
* #param {Boolean} elongate - The flag to extend cookie lifetime.
*/
const create = (name, value, elongate) => {
...
};
/**
* Function to get cookie.
*
* #param {String} key - The cookie identificatior to get.
* #returns {*}
*/
const get = (key) => {
...
};
/**
* Function to remove cookie.
*
* #param {String} key - The cookie identificator to remove.
*/
const remove = (key) => {
...
};
return {
create: create,
get: get,
remove: remove
}
})();
I'm doing it this way, but generated document looks terrible. I can not rewrite this part of the code to the ES6 standard. Can you please advice?
After some trying ai found #memberof
You can use it like this:
#memberof module:YourModuleName
Do not know, if it is correct, but after that I saw that method is showed in my module doc. page.
I'm trying to document some old code with JSDoc3, and I'm stuck trying to get it to include in the documentation the parameters to instance methods - or to show anything as an instance property at all. I suspect the problem is that the code does not follow the expected idiom for faking classes in javascript, but I want to get everything documented before I start rewriting anything. I've tried to make a small example of the problem, with the structure of the actual code:
/**
* Global function
* #param {Object} v Stuff that they're trying to avoid making global
* #return {Object} Updated v
*/
jsdoc_test = function( v ) {
/**
* Some stuff is defined in this namespace
* #namespace space
*/
var space = {};
/**
* Something that acts like a class
* #name space.someclass
* #memberOf space
* #constructor
* #type {function}
* #param {any} y blah blah
* #return {Object} The constructed object
*/
space.someclass = function( w ) {
var obj = {
source: w, // might need this again
derived: foo( w ), // what we usually need
etc: "etc" // and so on
};
/**
* This should be a member function, but it appears as a static property
* #name space.someclass.methodA
* #memberOf space.someclass
* #type {function}
* #instance
* #param {any} x Parameters do not appear in documentation
* #return {Object} this
*/
obj.methodA = function( x ) {
bar( x ); // or whatever methodA does
return this;
}
/**
* This should be a member function, but it doesn't show up at all
* #name space.someclass.methodB
* #memberOf space.someclass#
* #type {function}
* #param {any} y Parameters do not appear in documentation
* #return {Object} this
*/
obj.methodB = function( y ) {
baz( y ); // or whatever methodB does
return this;
}
return obj;
/**
* This should be a member function, but it doesn't show up at all
* #name space.someclass.methodC
* #memberOf space.someclass.prototype
* #type {function}
* #param {any} z Parameters do not appear in documentation
* #return {Object} this
*/
obj.methodC = function( z ) {
qux( z ); // or whatever methodC does
return this;
}
return obj;
}
// ...
}
I want all three methods to appear in the generated documentation as instance methods. As it is, methodA appears as a static property, while methodB and methodC (which follow suggestions from here) do not appear at all
How do I get JSDoc3 to document instance methods, with their parameters, without rewriting the code?
A combination of #instance, #memberOf & #method should do it:
/**
* This should now be a member function.
* #instance
* #memberOf space.someclass
* #method methodA
* #param {*} x Some parameter of any type.
* #return {Object} this.
*/
Looks like you're using too many tags on your code. When you use #constructor, you shouldn't need #name or #type, since those are covered by using constructor.
So, you've got two options, I think.
Use #constructor and remove the redundant (conflicting) tags:
/**
* Something that acts like a class
* #constructor space.someclass
* #memberOf space
* #param {any} y blah blah
* #return {Object} The constructed object
*/
Or, if you don't want to use the #constructor tag, add the appropriate hinting yourself:
/**
* Something that acts like a class
* #name space.someclass
* #memberOf space
* #kind class
* #param {any} y blah blah
* #return {Object} The constructed object
*/
In both cases, #type is redundant since you're documenting a class; the type would technically be the full name of your function (i.e., #type {space.someclass}).