Working with TypeScript helps us use many object-oriented features and type systems. But moving from JavaScript to TypeScript also requires significant time and effort to complete refactoring. However, VS Code provides TypeScript support for JSDoc, which allows us to annotate our JavaScript Code to make it more readable and maintainable.

What is the JSDoc?

First of all, let’s take a look at the introduction on the official website:

JSDoc 3 is an API documentation generator for JavaScript, similar to Javadoc or phpDocumentor. You add documentation comments directly to your source code, right alongside the code itself. The JSDoc tool will scan your source code and generate an HTML documentation website for you.

JSDoc (the latest version of JSDoc is JSDoc 3) is actually a tool that helps us generate JavaScript API documentation with comments in a specific format. Similar tools are Javadoc or phpDocumentor.

What comments can JSDoc make?

JSDoc’s purpose is to document the API of your JavaScript application or library. It is assumed that you will want to document things like modules, namespaces, classes, methods, method parameters, and so on.

JSDoc provides a reference to Block Tags for the types of comment Tags, but so far TypeScript only supports some Tags. In terms of syntax, JSDoc mainly borrows from closure-Compiler, while TypeScript has its own type syntax, so there are some differences. This section only covers typescript-based JSDoc usage in VS Code.

Define the object type — @type

Types that can be used in TypeScript include:

  • Basic types:
// Three ways to define an array type
/** * Define string Array type * @type {Array
      
       } */
      
var strArr = ['1'.'2'];

// Here are two other methods that work just as well as the first
/** * @type {Array.
      
       } */
      
/** * @type {string[]} */

/** * define Boolean type * @type {Boolean} */
var isSelected = false;

/** * define the string type * @type {string} */
var name = 'xyz';
Copy the code
  • TypeScriptTo add a type, such as:
/** * This is the TypeScript Navigator type * @type {Navigator} */
var navigator;

/** * This is the TypeScript Window type * @type {Window} */
var win;

/** * This is TypeScript's definition of HTML element type * @type {HTMLElement} */
var rootElement = document.getElementById('root');

Copy the code
  • Most JSDoc types
  1. Object type:
@type {{name: string, age: number}} */ @type {{name: string, age: number}
var cat = { name: 'miao'.age: 2 };
Copy the code
  1. Union type: Suitable for data types that may have one of more than one type, which can be determined from the list of types provided
// This is a string/Boolean type
/ * * * is used to describe a possible string or Boolean type * @ type {(string | Boolean)} * /
var stringOrBoolean = ' ';
stringOrBoolean = false;
Copy the code
  1. Defining function types
@type {function(string, Boolean): number} */
var function1;

@type {(s: string, b: Boolean) => number} */
var function2;

/** * use the built-in Function type, without specifying arguments and return values * @type {Function} */
var function 3;
Copy the code

Define custom types and properties — @typedef and @Property /@prop

  • If you want to create complex types that are used in JSDoc, you need to define the type using @typedef
  • Then use @Property or @prop to define the properties of the type.
  • When the definition is complete, use @type to use the user-defined type:
/** * @typedef {object} Animal - This is a custom Animal type * @property {string} name a complex type of string property * @property {number} age @prop {Boolean} [hasOwner] A Boolean property of a complex type, optional * @property {string[]=} Toys a String array property of a complex type, Optional * @prop {string} [ownerName='xyz'] a string property of a complex type. The default value is xyz, and * */ is optional

/** * @type {Animal} */
var animal = { name: 'miao'.age: 2.hasOwner: false }
Copy the code

Define the callback function — @callback

@callback is similar to @typedef, except that while @typedef defines object types, including function types, @callback defines function types.

/** * @callback Predicate * @param {string} data * @param {number} [index] * @returns {boolean} */
/** @type {Predicate} */
const ok = s= >! (s.length %2);
Copy the code

Define function arguments and return values — @param/@arg/@arguments and @return

  • @param/@arg/@arguments is used to define function arguments using the same type syntax as @type
  • @return is used to define the return value of a function. The argument is defined in a similar way to @typedef.
/** * @param {string} name - String type parameter * @param {string=} age - Optional, number type * @param {number} [hasOwner] - Optional Number type * @param {string} [ownerName="xyz"] - Optional argument with default value * @return {string} This is the return value */
function getAnimal(name, age, hasOwner, ownerName){
  // TODO
}
Copy the code

Define enumeration — @enum

Enumerations are a data type that is common in many languages but has no native support in JavaScript. But the most frustrating part is that enum is still a reserved keyword — it just hasn’t been implemented. TypeScript supports enum, and JSDoc provides support for enumerations based on @enum:

/** * FileType * @enum * @property {string} filetype. Image Image * @property {string} filetype. Video * @property {string} Filetype. Audio Audio * @property {string} filetype. Accessory */
export const FileType = {
  / * * * / picture
  Image: '1'.Video / * * * /
  Video: '2'.Audio / * * * /
  Audio: '3'./ * / * * accessories
  Accessory: '4'
}
Copy the code

Define the constructor — @class/@constructor

@class/@constructor can be used to define constructors, and only the new keyword is allowed to call the constructor.

/** * @constructor * @param {number} width width * @param {number} height */
function Rectangle(width, height) {
  this.width = width;
  this.height = height;
}

Rectangle.prototype.getArea = function() {
  return this.width * this.height
}
// It must be called by new, otherwise the editor will report an error
var rectrangele = new Rectangle();

Copy the code

Define this to refer to — @this

VS Code can do some type inference for us. However, there are some scenarios where we can’t make good inferences. Using @this helps us explicitly specify the type of this.

/**
 * @this {HTMLElement}
 */
function getScrollbarWidth() {
  return this.offsetWidth - this.scrollWidth
}
Copy the code

other

@type — Nullable and non-nullable

JSDoc has the concept of Nullable type and non-nullable type for @type, but TypeScript only allows the type to be null according to strictNullChecks. Consistency with JSDoc cannot be achieved by showing the labeling of non-Nullablity, for example:

/** * is marked in JSDoc as a possible number or null type * @type {? number} */

/** * is marked as number in JSDoc and cannot be null * @type {! number} */

 /** * Both TypeScript equivalents to * @type {number} */
Copy the code

Import definitions from other files in TypeScript

This is unique to TypeScript and not supported by JSDoc

// a.js
/** * @typedef Pet * @property name {string} */

/** * @type {Pet} */
var cat = { name: 'a' };
module.exports = {
  // cat
};

// b.js
/** * @param p {import('./a').Pet} */
function walk(p) {
  console.log(`${p.name}is walking! `)}// You can also alias imported types
/** * @typedef { import('./a').Pet } MyPet */
/** * @type {MyPet} */
var mimi = { name: 'mimi' }
Copy the code

Define the generic — @template

This is a definition type that is not mentioned in the JSDoc documentation and is only mentioned in Google Closure Compiler, but is supported in VS Code:

/** * @param {T} x * @param {S} y * @template {number|string} T * @template {number|string} S */
function foo(x,y) { x=y; }
Copy the code

Define the extension generic base class — @extends/@augments

None of these are used very much, so let’s take a look at some examples from the official documentation:

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

Note that @extends/@augments can only be used to define a generic parameter to a base class, and cannot be used to describe class inheritance:

class Animal {
  run() {

  }
}

/** * @extends {Animal} */
class Cat {}var cat = new Cat()
// There will be no code prompt
cat.run()
Copy the code

The resources

  • Type Checking JavaScript Files
  • Annotating JavaScript for the Closure Compiler
  • JSDoc