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.
@type
@param
(or@arg
or@argument
)@returns
(or@return
)@typedef
@callback
@template
@class
(or@constructor
)@this
@extends
(or@augments
)@enum
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.
@type
You can use the “@type” tag and reference a type name (either primitive, defined in a TypeScript declaration, or in a JSDoc “@typedef” tag). You can use most JSDoc types and any TypeScript type, 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 );Try
element .dataset .myData = "";
@type
can specify a union type — for example, something can be either a string or a boolean.
/**
* @type {(string | boolean)}
*/
var
Trysb ;
Note that parentheses are optional for union types.
/**
* @type {string | boolean}
*/
var
Trysb ;
You can specify array types using a variety of syntaxes:
/** @type {number[]} */
var
ns ;/** @type {Array.<number>} */
var
nds ;/** @type {Array<number>} */
var
Trynas ;
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
Tryvar9 ;
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
TryarrayLike ;
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 Closure syntax:
/** @type {function(string, boolean): number} Closure syntax */
var
sbn ;/** @type {(s: string, b: boolean) => number} TypeScript syntax */
var
Trysbn2 ;
Or you can just use the unspecified Function
type:
/** @type {Function} */
var
fn7 ;/** @type {function} */
var
Tryfn6 ;
Other types from Closure also work:
/**
* @type {*} - can be 'any' type
*/
var
star ;/**
* @type {?} - unknown type (same as 'any')
*/
var
Tryquestion ;
Casts
TypeScript borrows cast syntax from 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
TrytypeAssertedNumber = /** @type {number} */ (numberOrString );
Import types
You can also 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 p { import("./types").Pet }
*/
function
walk (p ) {
console .log (`Walking ${p .name }...`);}
Try
import types can also be used in type alias declarations:
/**
* @typedef { import("./types").Pet } Pet
*/
/**
* @type {Pet}
*/
var
myPet ;Try
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
Tryx =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 (Closure syntax)
* @param {string} [p3] - Another optional param (JSDoc syntax).
* @param {string} [p4="test"] - An optional param with a default value
* @return {string} This is the result
*/
function
stringsStringStrings (p1 ,p2 ,p3 ,p4 ) {// TODO
}
Try
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
Tryab () {}
@typedef
, @callback
, and @param
@typedef
may be used to define complex types. 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 ;Try
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
TryspecialTypeObject1 ;
@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 ;}
Try
@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
Tryok = (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 generic functions with the @template
tag:
/**
* @template T
* @param {T} x - A generic parameter that flows through to the return type
* @return {T}
*/
function
id (x ) {return
x ;}
const
a =id ("string");const
b =id (123);const
Tryc =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 ) {// ????
}
Try
Declaring generic classes or types is unsupported.
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 = newC (0);// C should only be called with new, but
// because it is JavaScript, this is allowed and
// considered an 'any'.
var
Tryresult =C (1);
They can also be declared as constructor functions, as described in the next section:
@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 Argument of type 'number' is not assignable to parameter of type 'string'.2345Argument of type 'number' is not assignable to parameter of type 'string'.}
/**
* @param {string} s
*/
C .prototype .initialize = function (s ) {this.
size =s .length ;};
var
c = newC (0);
c .size ;var
result =C (1);Value of type 'typeof C' is not callable. Did you mean to include 'new'?2348Value of type 'typeof C' is not callable. Did you mean to include 'new'?
Try
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!}
Try
@extends
When Javascript classes extend a generic base class, there is nowhere to specify what the type parameter should be. The @extends
tag provides a place for that type parameter:
/**
* @template T
* @extends {Set<T>}
*/
class
SortableSet extendsSet {// ...
}
Try
Note that @extends
only works with classes. Currently, there is no way for a constructor function extend a class.
@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 {number} */
const
JSDocState = {
BeginningOfLine : 0,
SawAsterisk : 1,
SavingComments : 2,};
Try
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,};
Try
MathFuncs .add1 ;
More examples
var
someObj = {/**
* @param {string} param1 - Docs on property assignments work
*/
x : function (param1 ) {},};
/**
* As do docs 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 functions expressions
* @param {number} x - A multiplier
*/
let
myArrow = (x ) =>x *x ;/**
* Which means it works for stateless function components in JSX too
* @param {{a: string, b: number}} test - Some param
*/
var
sfc = (test ) => <div >{test .a .charAt (0)}</div >;/**
* A parameter can be a class constructor, using 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 ();}
Try
Patterns that are known NOT to be supported
Referring to objects in the value space as types doesn’t work unless the object also creates a type, like a constructor function.
function
aNormalFunction () {}/**
* @type {aNormalFunction}
*/
var
wrong ;/**
* Use 'typeof' instead:
* @type {typeof aNormalFunction}
*/
var
Tryright ;
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
Tryright ;
Nullable types only have meaning if strictNullChecks
is on:
/**
* @type {?number}
* With strictNullChecks: true -- number | null
* With strictNullChecks: false -- number
*/
var
Trynullable ;
You can also use a union type:
/**
* @type {number | null}
* With strictNullChecks: true -- number | null
* With strictNullChecks: false -- number
*/
var
TryunionNullable ;
Non-nullable types have no meaning and are treated just as their original type:
/**
* @type {!number}
* Just has type number
*/
var
Trynormal ;
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)@readonly
(issue #17233)@yields
(issue #23857){@link …}
(issue #16498)