Things I found myself researching over and over without taking the time to write them down. Until now.
Table of Contents
- Should I use
{String}
vs{string}
or{Number}
vs{number}
...? - Type Expression: Optional vs Nullable vs Non-nullable
- When do I need to use the
@function
tag?
These aren't interchangeable type expressions. For example if a symbol is meant to hold a literal string you should use {string}
and not {String}
: (The same is true for {Number}
e.g. new Number(42)
vs {number}
e.g. 42
and {Boolean}
e.g. new Boolean
and {boolean}
e.g. false
.)
/** @param {String} x */
const a = x => x;
/** @param {string} x */
const b = x => x;
fn | Annotation | fn("foo") | fn(new String("foo")) |
---|---|---|---|
a | {String} x |
╳ | ✓ |
b | {string} x |
✓ | ╳ |
╳ represents the JSC_TYPE_MISMATCH error in GCC.
Examples have been compiled with the Google Closure Compiler and are available here.
Objects and arrays are covered respectively by the {Object}
and {Array}
type expressions which both handle literal and constructor expressions: ({}
vs new Object
and []
vs new Array
)
/** @param {Object} x */
const a = x => x;
/** @param {Array} x */
const b = x => x;
fn | Annotation | fn() | fn(<literal>) | fn(<constructor>) | fn(null) | fn(undefined) |
---|---|---|---|---|---|---|
a | {Object} x |
╳1 | ✓ | ✓ | ✓ | ╳2 |
b | {Array} x |
╳1 | ✓ | ✓ | ✓ | ╳2 |
╳1 represents the JSC_WRONG_ARGUMENT_COUNT error in GCC.
╳2 represents the JSC_TYPE_MISMATCH error in GCC.
Examples have been compiled using the Google Closure Compiler and are available here.
Note that arrays, objects (and functions) are nullable by default. So {Object}
is the same as {?Object}
which explains why a(null)
passed the type check.
Note that the following are already nullable, and thus prepending
?
is redundant, but is recommended so that the intent is clear and explicit:?Object
,?Array
,?Function
See Types in the Closure Type System
There are two type expressions: {function()}
and {Function}
. The former being preferred over the latter as it allows to document parameters and return values.
/** @param {Function} x */
const a = x => x;
/** @param {function()} x */
const b = x => x;
Code | {Function} x |
{function()} x |
---|---|---|
fn(() => 42); |
✓ | ✓ |
fn(function () { return 42 }); |
✓ | ✓ |
fn(new Function('return 42')); |
✓ | ✓ |
fn(); |
╳1 | ╳1 |
fn(null); |
✓ | ╳2 |
fn(undefined); |
╳2 | ╳2 |
╳1 represents the JSC_WRONG_ARGUMENT_COUNT error in GCC.
╳2 represents the JSC_TYPE_MISMATCH error in GCC.
Examples have been compiled using the Google Closure Compiler and are available here.
Note that {Function}
is the same as {?Function}
meaning that it is nullable by default.
A type expression is used to document the type of many different things such as a parameter, a variable or a property or the return value of a function. JSDoc supports the Google Closure Compiler Type System in type expressions.
/** @param {number} x */
const a = x => x;
/** @param {number=} x */
const b = x => x;
/** @param {number} [x] */
const c = x => x;
/** @param {number} [x=42] */
const d = x => x;
/** @param {!number} x */
const e = x => x;
/** @param {!number=} x */
const f = x => x;
/** @param {!number} [x] */
const g = x => x;
/** @param {!number} [x=42] */
const h = x => x;
/** @param {?number} x */
const i = x => x;
/** @param {?number=} x */
const j = x => x;
/** @param {?number} [x] */
const k = x => x;
/** @param {?number} [x=42] */
const l = x => x;
fn | Annotation | Expect | Default | fn() | fn("42") | fn(null) | fn(undefined) | fn(42) |
---|---|---|---|---|---|---|---|---|
a | {number} x |
Number | ╳1 | ╳2 | ╳2 | ╳2 | ✓ | |
b | {number=} x |
Number or undefined |
undefined |
✓ | ╳2 | ╳2 | ✓ | ✓ |
c | {number} [x] |
Number or undefined |
undefined |
✓ | ╳2 | ╳2 | ✓ | ✓ |
d | {number} [x=42] |
Number or undefined |
42 |
✓ | ╳2 | ╳2 | ✓ | ✓ |
e | {!number} x |
Number | ╳1 | ╳2 | ╳2 | ╳2 | ✓ | |
f | {!number=} x |
Number or undefined |
undefined |
✓ | ╳2 | ╳2 | ✓ | ✓ |
g | {!number} [x] |
Number or undefined |
undefined |
✓ | ╳2 | ╳2 | ✓ | ✓ |
h | {!number} [x=42] |
Number or undefined |
42 |
✓ | ╳2 | ╳2 | ✓ | ✓ |
i | {?number} x |
Number or null |
╳1 | ╳2 | ✓ | ╳2 | ✓ | |
j | {?number=} x |
Number, null or undefined |
undefined |
✓ | ╳2 | ✓ | ✓ | ✓ |
k | {?number} [x] |
Number, null or undefined |
undefined |
✓ | ╳2 | ✓ | ✓ | ✓ |
l | {?number} [x=42] |
Number, null or undefined |
42 |
✓ | ╳2 | ✓ | ✓ | ✓ |
╳1 represents the JSC_WRONG_ARGUMENT_COUNT error in GCC.
╳2 represents the JSC_TYPE_MISMATCH error in GCC.
Examples have been compiled with the Google Closure Compiler and are available here.
This would be necessary when a function gets assigned to a variable for example.
This marks an object as being a function, even though it may not appear to be one to the parser. It sets the doclet's @kind to 'function'.
See JSDoc @function tag documentation.
If we dump the doclets of index.js with: jsdoc -X index.js
// index.js
/** @param {?} y */
function a(y) {}
/** @param {?} y */
const b = a;
/**
* @function
* @param {?} y
*/
const c = a;
Doclet for a
:
{
// ...
"name": "a",
"longname": "a",
"kind": "function",
"scope": "global"
}
Doclet for b
:
{
// ...
"name": "b",
"longname": "b",
"kind": "constant",
"scope": "global"
}
Doclet for c
:
{
// ...
"name": "b",
"longname": "b",
"kind": "function",
"scope": "global"
}
We can see that b
doesn't appear as a function to the JSDoc parser. This isn't the case for c
as we explicitly marked it as such with the @function
tag.