Type Checking in JavaScript files with JS Doc
JSDoc annotations to provide type information in JavaScript files
You can type-check and report errors in JavaScript files using JSDoc annotations, checked by the TypeScript compiler (version 2.3 or later).
This lets you use JavaScript with types, without a compile step, and while keeping the original file format. 🌿
Below are the constructs TypeScript currently supports when using JSDoc annotations to add type information to JavaScript files.
@type
@param (or @arg or @argument)
@return (or @returns)
@typedef
@callback
@template
@this
@extends (or @augments)
@enum@type
The type tag references a type name. You can use any TypeScript type, and most JSDoc types too.
/** @type {string} */
var value;
/** @type {number} */
var myNumber;
/** @type {HTMLElement} */
var myElement;@type can be defined to accept a set of types, like only string | boolean
/** @type {string | boolean} */
var value;@type can also accept specific inner types, like an array of numbers or an object with a: string and b: number
/** @type {Array<number>} */
var numberArray;
/** @type {{ a: string, b: number }} */
var valueObject;@type definitions for a function can look like this:
/** @type {function(string, boolean): number} Closure syntax */
var calc;
/** @type {function} */
var calc;@type can also express any or unknown:
/**
* @type {*} - can be 'any' type
*/
var value1;
/**
* @type {?} - unknown type (same as 'any')
*/
var value2;@type can point to a type defined in another file and then be imported:
/**
* @typedef { import("./button.types").props } props
*/
var button;@params and @returns
@param documents a function's arguments. It's similar to @type, but with a parameter name attached. @returns defines the annotated function's return type; you can also use @return.
/**
* Calc function takes 4 arguments
* @param {number} num1 - A number param.
* @param {number=} num2 - An optional param (Closure syntax)
* @param {number} [num3] - Another optional param (JSDoc syntax).
* @param {number} [num4="test"] - An optional param with a default value
* @returns {number} This is the return result
*/
function calc(num1, num2, num3, num4){
// TODO
}@param can be nested, as shown below:
/**
* calculation method
* @param {Object} options - The shape is the same as SpecialType above
* @param {string} options.prop1
* @param {number} options.prop2
* @param {number=} options.prop3 // optional parameter
* @param {number} [options.prop4=42] //optional parameter with default value
*/
function calculation({prop1, prop2, prop3, prop4}) {
return (options.prop3 || 1001) + options.prop4;
}@typedef and @callbacks
@typedef lets you define complex types. You can do the same inline 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 - a number property of SpecialType which is optional
* @property {number} [options.prop4=42] - a number property of SpecialType which is optional parameter with default value
*/
/** @type {SpecialType} */
function calculation({prop1, prop2, prop3, prop4}) {
return (options.prop3 || 1001) + options.prop4;
}@callback is similar to @typedef, but it defines a function type instead of an object type.
/**
* @callback DoubleLength
* @param {string} data
* @param {number} [index]
* @returns {boolean}
*/
/** @type {DoubleLength} */
const ok = data => !(data.length % 2);The same callback can be defined with @typedef instead, as shown below:
/** @typedef {(data: string, index?: number) => boolean} DoubleLength */@template
For generic type definitions, use @template. The example below ties the argument type to the return type:
/**
* @template S
* @param {S} p1 - A generic parameter that flows through to the return type
* @return {S}
*/
function id(data){ return data }@this
If you need to set the type of this explicitly, use the @this annotation.
/**
* @this {HTMLElement}
* @param {*} e
*/
function callback(e) {
this.width = parseInt(e)
}@extends
A class that extends an existing generic base class can be annotated with @extends.
/**
* @template T
* @extends {Map<T>}
*/
class HashMap extends Map {
// ...
}@enum
@enum defines an object literal whose members are all of a specified type.
/** @enum {number} */
const BankAccount = {
CurrentBalance: 1000,
SavingsBalance: 200,
UnclearedBalance: 200,
}That's all, folks. Now you can write your JavaScript with type safety. ⛑
Anyone using your typed code gets proper IDE tooltips showing what types to pass, and your IDE will catch type errors directly.
Cheers!!✌🏻