JSDoc Reference #
The list below outlines which constructs are currently supported when using JSDoc annotations to provide type information in JavaScript files.
Note any tags which are not explicitly listed below (such as @async
)
are not yet supported.
Types #
Classes #
- Property Modifiers
@public
,@private
,@protected
,@readonly
@override
@extends
(or@augments
)@implements
@class
(or@constructor
)@this
Documentation #
Documentation tags work in both TypeScript and JavaScript.
Other #
The meaning is usually the same, or a superset, of the meaning of the tag given at jsdoc.app. The code below describes the differences and gives some example usage of each tag.
Note: You can use the playground to explore JSDoc support.
Types #
@type
#
You can reference types with the “@type” tag. The type can be:
- Primitive, like
string
ornumber
. - Declared in a TypeScript declaration, either global or imported.
- Declared in a JSDoc
@typedef
tag.
You can use most JSDoc type syntax and any TypeScript syntax, from
the
most basic like string
to
the most advanced, like
conditional types.
/**
* @type {string}
*/
var s;
Â
/** @type {Window} */
var win;
Â
/** @type {PromiseLike<string>} */
var promisedString;
Â
// You can specify an HTML Element with DOM properties
/** @type {HTMLElement} */
var myElement = document.querySelector(selector);
element.dataset.myData = "";
@type
can specify a union type — for example, something can be
either a string or a boolean.
/**
* @type {string | boolean}
*/
var sb;
You can specify array types using a variety of syntaxes:
/** @type {number[]} */
var ns;
/** @type {Array.<number>} */
var jsdoc;
/** @type {Array<number>} */
var nas;
You can also specify object literal types. For example, an object with properties ‘a’ (string) and ‘b’ (number) uses the following syntax:
/** @type {{ a: string, b: number }} */
var var9;
You can specify map-like and array-like objects using string and number index signatures, using either standard JSDoc syntax or TypeScript syntax.
/**
* A map-like object that maps arbitrary `string` properties to `number`s.
*
* @type {Object.<string, number>}
*/
var stringToNumber;
Â
/** @type {Object.<number, object>} */
var arrayLike;
The preceding two types are equivalent to the TypeScript types
{ [x: string]: number }
and { [x: number]: any }
. The compiler
understands both syntaxes.
You can specify function types using either TypeScript or Google Closure syntax:
/** @type {function(string, boolean): number} Closure syntax */
var sbn;
/** @type {(s: string, b: boolean) => number} TypeScript syntax */
var sbn2;
Or you can just use the unspecified Function
type:
/** @type {Function} */
var fn7;
/** @type {function} */
var fn6;
Other types from Closure also work:
/**
* @type {*} - can be 'any' type
*/
var star;
/**
* @type {?} - unknown type (same as 'any')
*/
var question;
Casts #
TypeScript borrows cast syntax from Google Closure. This lets you cast
types to other types by adding a @type
tag before any parenthesized
expression.
/**
* @type {number | string}
*/
var numberOrString = Math.random() < 0.5 ? "hello" : 100;
var typeAssertedNumber = /** @type {number} */ (numberOrString);
You can even cast to const
just like TypeScript:
let one = /** @type {const} */(1);
Import types #
You can import declarations from other files using import types. This syntax is TypeScript-specific and differs from the JSDoc standard:
// @filename: types.d.ts
export type Pet = {
name: string,
};
Â
// @filename: main.js
/**
* @param {import("./types").Pet} p
*/
function walk(p) {
console.log(`Walking ${p.name}...`);
}
import types can be used in type alias declarations:
/**
* @typedef {import("./types").Pet} Pet
*/
Â
/**
* @type {Pet}
*/
var myPet;
myPet.name;
import types can be used to get the type of a value from a module if you don’t know the type, or if it has a large type that is annoying to type:
/**
* @type {typeof import("./accounts").userAccount}
*/
var x = require("./accounts").userAccount;
@param
and @returns
#
@param
uses the same type syntax as @type
, but adds a parameter
name. The parameter may also be declared optional by surrounding the
name with square brackets:
// Parameters may be declared in a variety of syntactic forms
/**
* @param {string} p1 - A string param.
* @param {string=} p2 - An optional param (Google Closure syntax)
* @param {string} [p3] - Another optional param (JSDoc syntax).
* @param {string} [p4="test"] - An optional param with a default value
* @returns {string} This is the result
*/
function stringsStringStrings(p1, p2, p3, p4) {
// TODO
}
Likewise, for the return type of a function:
/**
* @return {PromiseLike<string>}
*/
function ps() {}
Â
/**
* @returns {{ a: string, b: number }} - May use '@returns' as well as '@return'
*/
function ab() {}
@typedef
, @callback
, and @param
#
You can define complex types with @typedef
. Similar syntax works with
@param
.
/**
* @typedef {Object} SpecialType - creates a new type named 'SpecialType'
* @property {string} prop1 - a string property of SpecialType
* @property {number} prop2 - a number property of SpecialType
* @property {number=} prop3 - an optional number property of SpecialType
* @prop {number} [prop4] - an optional number property of SpecialType
* @prop {number} [prop5=42] - an optional number property of SpecialType with default
*/
Â
/** @type {SpecialType} */
var specialTypeObject;
specialTypeObject.prop3;
You can use either object
or Object
on the first line.
/**
* @typedef {object} SpecialType1 - creates a new type named 'SpecialType'
* @property {string} prop1 - a string property of SpecialType
* @property {number} prop2 - a number property of SpecialType
* @property {number=} prop3 - an optional number property of SpecialType
*/
Â
/** @type {SpecialType1} */
var specialTypeObject1;
@param
allows a similar syntax for one-off type specifications. Note
that the nested property names must be prefixed with the name of the
parameter:
/**
* @param {Object} options - The shape is the same as SpecialType above
* @param {string} options.prop1
* @param {number} options.prop2
* @param {number=} options.prop3
* @param {number} [options.prop4]
* @param {number} [options.prop5=42]
*/
function special(options) {
return (options.prop4 || 1001) + options.prop5;
}
@callback
is similar to @typedef
, but it specifies a function type
instead of an object type:
/**
* @callback Predicate
* @param {string} data
* @param {number} [index]
* @returns {boolean}
*/
Â
/** @type {Predicate} */
const ok = (s) => !(s.length % 2);
Of course, any of these types can be declared using TypeScript syntax in
a single-line @typedef
:
/** @typedef {{ prop1: string, prop2: string, prop3?: number }} SpecialType */
/** @typedef {(data: string, index?: number) => boolean} Predicate */
@template
#
You can declare type parameters with the @template
tag. This lets you
make functions, classes, or types that are generic:
/**
* @template T
* @param {T} x - A generic parameter that flows through to the return type
* @returns {T}
*/
function id(x) {
return x;
}
Â
const a = id("string");
const b = id(123);
const c = id({});
Use comma or multiple tags to declare multiple type parameters:
/**
* @template T,U,V
* @template W,X
*/
You can also specify a type constraint before the type parameter name. Only the first type parameter in a list is constrained:
/**
* @template {string} K - K must be a string or string literal
* @template {{ serious(): string }} Seriousalizable - must have a serious method
* @param {K} key
* @param {Seriousalizable} object
*/
function seriousalize(key, object) {
// ????
}
Finally, you can specify a default for a type parameter:
/** @template [T=object] */
class Cache {
/** @param {T} initial */
constructor(initial) {
}
}
let c = new Cache()
Classes #
Classes can be declared as ES6 classes.
class C {
/**
* @param {number} data
*/
constructor(data) {
// property types can be inferred
this.name = "foo";
Â
// or set explicitly
/** @type {string | null} */
this.title = null;
Â
// or simply annotated, if they're set elsewhere
/** @type {number} */
this.size;
Â
this.initialize(data); // Should error, initializer expects a string
}
/**
* @param {string} s
*/
initialize = function (s) {
this.size = s.length;
};
}
Â
var c = new C(0);
Â
// C should only be called with new, but
// because it is JavaScript, this is allowed and
// considered an 'any'.
var result = C(1);
They can also be declared as constructor functions; use
@constructor
along with
@this
for this.
Property Modifiers #
@public
, @private
, and @protected
work exactly like public
,
private
, and protected
in TypeScript:
// @ts-check
Â
class Car {
constructor() {
/** @private */
this.identifier = 100;
}
Â
printIdentifier() {
console.log(this.identifier);
}
}
Â
const c = new Car();
console.log(c.identifier);
@public
is always implied and can be left off, but means that a property can be reached from anywhere.@private
means that a property can only be used within the containing class.@protected
means that a property can only be used within the containing class, and all derived subclasses, but not on dissimilar instances of the containing class.
@public
, @private
, and @protected
do not work in constructor
functions.
@readonly
#
The @readonly
modifier ensures that a property is only ever written to
during initialization.
// @ts-check
Â
class Car {
constructor() {
/** @readonly */
this.identifier = 100;
}
Â
printIdentifier() {
console.log(this.identifier);
}
}
Â
const c = new Car();
console.log(c.identifier);
@override
#
@override
works the same way as in TypeScript; use it on methods that
override a method from a base class:
export class C {
m() { }
}
class D extends C {
/** @override */
m() { }
}
Set noImplicitOverride: true
in tsconfig to check overrides.
@extends
#
When JavaScript classes extend a generic base class, there is no
JavaScript syntax for passing a type argument. The @extends
tag allows
this:
/**
* @template T
* @extends {Set<T>}
*/
class SortableSet extends Set {
// ...
}
Note that @extends
only works with classes. Currently, there is no way
for a constructor function to extend a class.
@implements
#
In the same way, there is no JavaScript syntax for implementing a
TypeScript interface. The @implements
tag works just like in
TypeScript:
/** @implements {Print} */
class TextBook {
print() {
// TODO
}
}
@constructor
#
The compiler infers constructor functions based on this-property
assignments, but you can make checking stricter and suggestions better
if you add a @constructor
tag:
/**
* @constructor
* @param {number} data
*/
function C(data) {
// property types can be inferred
this.name = "foo";
Â
// or set explicitly
/** @type {string | null} */
this.title = null;
Â
// or simply annotated, if they're set elsewhere
/** @type {number} */
this.size;
Â
this.initialize(data);
}
/**
* @param {string} s
*/
C.prototype.initialize = function (s) {
this.size = s.length;
};
Â
var c = new C(0);
c.size;
Â
var result = C(1);
Note: Error messages only show up in JS codebases with a JSConfig and
checkJs
enabled.
With @constructor
, this
is checked inside the constructor function
C
, so you will get suggestions for the initialize
method and an
error if you pass it a number. Your editor may also show warnings if you
call C
instead of constructing it.
Unfortunately, this means that constructor functions that are also
callable cannot use @constructor
.
@this
#
The compiler can usually figure out the type of this
when it has some
context to work with. When it doesn’t, you can explicitly specify the
type of this
with @this
:
/**
* @this {HTMLElement}
* @param {*} e
*/
function callbackForLater(e) {
this.clientHeight = parseInt(e); // should be fine!
}
Documentation #
@deprecated
#
When a function, method, or property is deprecated you can let users
know by marking it with a /** @deprecated */
JSDoc comment. That
information is surfaced in completion lists and as a suggestion
diagnostic that editors can handle specially. In an editor like VS Code,
deprecated values are typically displayed in a strike-through style
like this.
/** @deprecated */
const apiV1 = {};
const apiV2 = {};
Â
apiV;
Â
Â
@see
#
@see
lets you link to other names in your program:
type Box<T> = { t: T }
/** @see Box for implementation details */
type Boxify<T> = { [K in keyof T]: Box<T> };
Some editors will turn Box
into a link to make it easy to jump there
and back.
@link
#
@link
is like @see
, except that it can be used inside other tags:
type Box<T> = { t: T }
/** @returns A {@link Box} containing the parameter. */
function box<U>(u: U): Box<U> {
return { t: u };
}
Other #
@enum
#
The @enum
tag allows you to create an object literal whose members are
all of a specified type. Unlike most object literals in JavaScript, it
does not allow other members. @enum
is intended for compatibility with
Google Closure’s @enum
tag.
/** @enum {number} */
const JSDocState = {
BeginningOfLine: 0,
SawAsterisk: 1,
SavingComments: 2,
};
Â
JSDocState.SawAsterisk;
Note that @enum
is quite different from, and much simpler than,
TypeScript’s enum
. However, unlike TypeScript’s enums, @enum
can
have any type:
/** @enum {function(number): number} */
const MathFuncs = {
add1: (n) => n + 1,
id: (n) => -n,
sub1: (n) => n - 1,
};
Â
MathFuncs.add1;
@author
#
You can specify the author of an item with @author
:
/**
* Welcome to awesome.ts
* @author Ian Awesome <i.am.awesome@example.com>
*/
Remember to surround the email address with angle brackets. Otherwise,
@example
will be parsed as a new tag.
Other supported patterns #
var someObj = {
/**
* @param {string} param1 - JSDocs on property assignments work
*/
x: function (param1) {},
};
Â
/**
* As do jsdocs on variable assignments
* @return {Window}
*/
let someFunc = function () {};
Â
/**
* And class methods
* @param {string} greeting The greeting to use
*/
Foo.prototype.sayHi = (greeting) => console.log("Hi!");
Â
/**
* And arrow function expressions
* @param {number} x - A multiplier
*/
let myArrow = (x) => x * x;
Â
/**
* Which means it works for function components in JSX too
* @param {{a: string, b: number}} props - Some param
*/
var fc = (props) => <div>{props.a.charAt(0)}</div>;
Â
/**
* A parameter can be a class constructor, using Google Closure syntax.
*
* @param {{new(...args: any[]): object}} C - The class to register
*/
function registerClass(C) {}
Â
/**
* @param {...string} p1 - A 'rest' arg (array) of strings. (treated as 'any')
*/
function fn10(p1) {}
Â
/**
* @param {...string} p1 - A 'rest' arg (array) of strings. (treated as 'any')
*/
function fn9(p1) {
return p1.join();
}
Unsupported patterns #
Postfix equals on a property type in an object literal type doesn’t specify an optional property:
/**
* @type {{ a: string, b: number= }}
*/
var wrong;
/**
* Use postfix question on the property name instead:
* @type {{ a: string, b?: number }}
*/
var right;
Nullable types only have meaning if
strictNullChecks
is on:
/**
* @type {?number}
* With strictNullChecks: true -- number | null
* With strictNullChecks: false -- number
*/
var nullable;
The TypeScript-native syntax is a union type:
/**
* @type {number | null}
* With strictNullChecks: true -- number | null
* With strictNullChecks: false -- number
*/
var unionNullable;
Non-nullable types have no meaning and are treated just as their original type:
/**
* @type {!number}
* Just has type number
*/
var normal;
Unlike JSDoc’s type system, TypeScript only allows you to mark types as
containing null or not. There is no explicit non-nullability — if
strictNullChecks is on, then number
is not nullable. If it is off,
then number
is nullable.
Unsupported tags #
TypeScript ignores any unsupported JSDoc tags.
The following tags have open issues to support them:
@const
( issue #19672)@inheritdoc
( issue #23215)@memberof
( issue #7237)@yields
( issue #23857)
::: _attribution
© 2012-2023 Microsoft
Licensed under the Apache License, Version 2.0.
https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html{._attribution-link}
:::