Support the JSDoc

The following is a list of previously supported JSDoc annotations that you can use to add type information to JavaScript files.

Note that any tags not 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 meanings they represent are usually the same or a superset of those given above on usejsdoc.org. The following code describes the differences and gives some examples.

@type

You can use the @type tag and reference a type name (a primitive type, a type declared in TypeScript, or a type specified in the @typedef tag in JSDoc). You can use any TypeScript type and most JSDoc 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 = ' ';
Copy the code

@type can specify the union type – for example, the union of string and Boolean types.

/ * * *@type {(string | boolean)}* /
var sb;
Copy the code

Note that parentheses are optional.

/ * * *@type {string | boolean}* /
var sb;
Copy the code

There are several ways to specify an array type:

/ * *@type {number[]} * /
var ns;
/ * *@type {Array.<number>} * /
var nds;
/ * *@type {Array<number>} * /
var nas;
Copy the code

You can also specify object literal types. For example, an object with attributes a (string) and b (number) uses the following syntax:

/ * *@type {{ a: string, b: number }} * /
var var9;
Copy the code

You can specify Map-like and Array-like objects using string and digitally indexed signatures, using standard JSDoc 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;
Copy the code

These types are equivalent to {[x: string]: number} and {[x: number]: any} in TypeScript. The compiler recognizes both syntax.

You can specify function types using TypeScript or Closure syntax.

/ * *@type {function(string, boolean): number} Closure syntax */
var sbn;
/ * *@type {(s: string, b: boolean) => number} Typescript syntax */
var sbn2;
Copy the code

Or use the undefined Function type:

/ * *@type {Function} * /
var fn7;
/ * *@type {function} * /
var fn6;
Copy the code

Closure’s other types can also be used:

/ * * *@type {*} - can be 'any' type
 */
var star;
/ * * *@type {? } - unknown type (same as 'any')
 */
var question;
Copy the code

conversion

TypeScript borrows conversion syntax from Closure. You can convert one type to another by using the @type tag before the parenthesis expression

/ * * *@type {number | string}* /
var numberOrString = Math.random() < 0.5 ? "hello" : 100;
var typeAssertedNumber = / * *@type {number} * / (numberOrString)
Copy the code

The import type

You can import declarations from other files using the import type. This syntax is TypeScript specific and differs from the JSDoc standard:

/ * * *@param p { import("./a").Pet }
 */
function walk(p) {
    console.log(`Walking ${p.name}. `);
}
Copy the code

Import types can also be used in type alias declarations:

/ * * *@typedef { import("./a").Pet } Pet* /

/ * * *@type {Pet}* /
var myPet;
myPet.name;
Copy the code

Import types can be used to get a value from a module.

/ * * *@type {typeof import("./a").x }* /
var x = require("./a").x;
Copy the code

@paramand@returns

@param has the same syntax as @type, but with an added parameter name. You can use [] to declare parameters as optional:

// 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
}
Copy the code

The return type of the function is similar:

/ * * *@return {PromiseLike<string>}* /
function ps(){}

/ * * *@returns {{ a: string, b: number }} - May use '@returns' as well as '@return'
 */
function ab(){}
Copy the code

@typedef.@callback, and@param

@typedef can be used to declare complex types. Similar syntax to @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;
Copy the code

You can use object or object on the first line.

/ * * *@typedef {object} SpecialType1 - creates a new type named 'SpecialType1'
 * @property {string} prop1 - a string property of SpecialType1
 * @property {number} prop2 - a number property of SpecialType1
 * @property {number=} prop3 - an optional number property of SpecialType1
 */
/ * *@type {SpecialType1} * /
var specialTypeObject1;
Copy the code

@param allows a similar syntax. Note that nested attribute names must be prefixed with parameter names:

/ * * *@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;
}
Copy the code

@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);
Copy the code

Of course, all of these types can be declared on a single line using the TypeScript @typedef syntax:

/ * *@typedef {{ prop1: string, prop2: string, prop3? : number }} SpecialType */
/ * *@typedef {(data: string, index? : number) => boolean} Predicate */
Copy the code

@template

Use @template to declare generics:

/ * * *@template T
 * @param {T} x - A generic parameter that flows through to the return type
 * @return {T}* /
function id(x){ return x }
Copy the code

Use commas or multiple tags to declare multiple type parameters:

/ * * *@template T,U,V
 * @template W,X
 */
Copy the code

You can also specify a type constraint before the parameter name. Only the first item type parameter of the list will be 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) {
  / /??????
}
Copy the code

@constructor

The compiler extrapses constructors from this assignment, but you can make the inspection more strict and prompt more friendly by adding a @constructor flag:

/ * * *@constructor
 * @param {number} data* /
function C(data) {
  this.size = 0;
  this.initialize(data); // Should error, initializer expects a string
}
/ * * *@param {string} s* /
C.prototype.initialize = function (s) {
  this.size = s.length
}

var c = new C(0);
var result = C(1); // C should only be called with new
Copy the code

With @constructor, this will be checked in the constructor C, so you’ll get a prompt in the initialize method, and an error if you pass in a number. If you call C directly instead of constructing it, you also get an error.

Unfortunately, this means that constructors that can be both constructed and called directly cannot be used with @constructor.

@this

The compiler can often infer the type of this from the context. But you can use @this to specify its type explicitly:

/ * * *@this {HTMLElement}
 * @param {*} e* /
function callbackForLater(e) {
    this.clientHeight = parseInt(e) // should be fine!
}
Copy the code

@extends

When a JavaScript class inherits from a base class, there is no place to specify the type of the type parameter. The @extends tag, however, provides a way to:

/ * * *@template T
 * @extends {Set<T>}* /
class SortableSet extends Set {
  // ...
}
Copy the code

Note that @extends only applies to classes. Currently, it is not possible to implement a constructor inheritance class.

@enum

The @enum flag allows you to create an object literal whose members have a specific type. Unlike most object literals in JavaScript, it does not allow additional members to be added.

/ * *@enum {number} * /
const JSDocState = {
  BeginningOfLine: 0.SawAsterisk: 1.SavingComments: 2,}Copy the code

Note that @enum is very different from @enum in TypeScript. It’s much simpler. However, unlike TypeScript enumerations, @enum can be of any type:

/ * *@enum {function(number): number} * /
const Math = {
  add1: n= > n + 1.id: n= > -n,
  sub1: n= > n - 1,}Copy the code

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 fc = (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();
}
Copy the code

Known unsupported patterns

It is not acceptable to treat an object as a type in the value space unless the object creates a type, such as a constructor.

function aNormalFunction() {}/ * * *@type {aNormalFunction}* /
var wrong;
/**
 * Use 'typeof' instead:
 * @type {typeof aNormalFunction}* /
var right;
Copy the code

The = suffix on an object literal property does not specify that the property is optional:

/ * * *@type {{ a: string, b: number= }} * /
var wrong;
/**
 * Use postfix question on the property name instead:
 * @type {{ a: string, b? : number }} * /
var right;
Copy the code

The Nullable type only works if strictNullChecks are enabled:

/ * * *@type {? number}
 * With strictNullChecks: true -- number | null
 * With strictNullChecks: off  -- number
 */
var nullable;
Copy the code

Non-nullable types have no meaning and are treated as their original types:

/ * * *@type {! number}
 * Just has type number
 */
var normal;
Copy the code

Unlike the JSDoc type system, TypeScript only allows you to mark types as packages that do not contain null. No explicit non-nullable — if strictNullChecks is enabled, then the number is non-null. If it is not enabled, then number can be null.