JSDoc 参考资料

下面的列表概述了在使用 JSDoc 注释在 JavaScript 文件中提供类型信息时当前支持哪些结构。

¥The list below outlines which constructs are currently supported when using JSDoc annotations to provide type information in JavaScript files.

请注意,尚不支持以下未明确列出的任何标签(例如 @async)。

¥Note any tags which are not explicitly listed below (such as @async) are not yet supported.

类型

¥Types

¥Classes

文档

¥Documentation

文档标签适用于 TypeScript 和 JavaScript。

¥Documentation tags work in both TypeScript and JavaScript.

其他

¥Other

含义通常与 jsdoc.app 处给出的标签的含义相同或超集。下面的代码描述了差异并给出了每个标签的一些示例用法。

¥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.

注意:你可以使用 探索 JSDoc 支持的在线运行

¥Note: You can use the playground to explore JSDoc support.

类型

¥Types

@type

你可以使用 “@type” 标记引用类型。类型可以是:

¥You can reference types with the “@type” tag. The type can be:

  1. 基础类型,如 stringnumber

    ¥Primitive, like string or number.

  2. 在 TypeScript 声明中声明,全局或导入。

    ¥Declared in a TypeScript declaration, either global or imported.

  3. 在 JSDoc @typedef 标签中声明。

    ¥Declared in a JSDoc @typedef tag.

你可以使用大多数 JSDoc 类型语法和任何 TypeScript 语法,从 最基本的像 string最高级的,比如条件类型

¥You can use most JSDoc type syntax and any TypeScript syntax, from the most basic like string to the most advanced, like conditional types.

js
/**
 
* @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 = "";
Try

@type 可以指定联合类型 - 例如,某些内容可以是字符串或布尔值。

¥@type can specify a union type — for example, something can be either a string or a boolean.

js
/**
 
* @type {string | boolean}
*/
var sb;
Try

你可以使用多种语法指定数组类型:

¥You can specify array types using a variety of syntaxes:

js
/** @type {number[]} */
var ns;
/** @type {Array.<number>} */
var jsdoc;
/** @type {Array<number>} */
var nas;
Try

你还可以指定对象字面类型。例如,具有属性 ‘a’(字符串)和 ‘b’(数字)的对象使用以下语法:

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

js
/** @type {{ a: string, b: number }} */
var var9;
Try

你可以使用标准 JSDoc 语法或 TypeScript 语法,使用字符串和数字索引签名来指定类映射和类数组对象。

¥You can specify map-like and array-like objects using string and number index signatures, using either standard JSDoc syntax or TypeScript syntax.

js
/**
 
* A map-like object that maps arbitrary `string` properties to `number`s.
 
* * @type {Object.<string, number>}
*/
var stringToNumber;
 
/** @type {Object.<number, object>} */
var arrayLike;
Try

上述两种类型相当于 TypeScript 类型 { [x: string]: number }{ [x: number]: any }。编译器理解这两种语法。

¥The preceding two types are equivalent to the TypeScript types { [x: string]: number } and { [x: number]: any }. The compiler understands both syntaxes.

你可以使用 TypeScript 或 Google Closure 语法指定函数类型:

¥You can specify function types using either TypeScript or Google Closure syntax:

js
/** @type {function(string, boolean): number} Closure syntax */
var sbn;
/** @type {(s: string, b: boolean) => number} TypeScript syntax */
var sbn2;
Try

或者你可以只使用未指定的 Function 类型:

¥Or you can just use the unspecified Function type:

js
/** @type {Function} */
var fn7;
/** @type {function} */
var fn6;
Try

Closure 的其他类型也可以工作:

¥Other types from Closure also work:

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

Casts

TypeScript 借鉴了 Google Closure 的强制转换语法。这使你可以通过在任何带括号的表达式之前添加 @type 标记来将类型转换为其他类型。

¥TypeScript borrows cast syntax from Google Closure. This lets you cast types to other types by adding a @type tag before any parenthesized expression.

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

你甚至可以像 TypeScript 一样转换为 const

¥You can even cast to const just like TypeScript:

js
let one = /** @type {const} */(1);
Try

导入类型

¥Import types

你可以使用导入类型从其他文件导入声明。此语法特定于 TypeScript,与 JSDoc 标准不同:

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

js
// @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}...`);
}
Try

导入类型可以在类型别名声明中使用:

¥import types can be used in type alias declarations:

js
/**
 
* @typedef {import("./types").Pet} Pet
*/
 
/**
 
* @type {Pet}
*/
var myPet;
myPet.name;
Try

import types 可以用来从模块中获取值的类型,如果你不知道类型,或者如果它有一个大的类型,输入起来很烦人:

¥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:

js
/**
 
* @type {typeof import("./accounts").userAccount}
*/
var x = require("./accounts").userAccount;
Try

@param@returns

¥@param and @returns

@param 使用与 @type 相同的类型语法,但添加了参数名称。该参数也可以通过用方括号括起名称来声明为可选:

¥@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:

js
// 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
}
Try

同样,对于函数的返回类型:

¥Likewise, for the return type of a function:

js
/**
 
* @return {PromiseLike<string>}
*/
function ps() {}
 
/**
 
* @returns {{ a: string, b: number }} - May use '@returns' as well as '@return'
*/
function ab() {}
Try

@typedef@callback@param

¥@typedef, @callback, and @param

你可以使用 @typedef 定义复杂类型。类似的语法适用于 @param

¥You can define complex types with @typedef. Similar syntax works with @param.

js
/**
 
* @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;
Try

你可以在第一行使用 objectObject

¥You can use either object or Object on the first line.

js
/**
 
* @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;
Try

@param 允许对一次性类型规范使用类似的语法。请注意,嵌套的属性名称必须以参数名称为前缀:

¥@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:

js
/**
 
* @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@typedef 类似,但它指定的是函数类型而不是对象类型:

¥@callback is similar to @typedef, but it specifies a function type instead of an object type:

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

当然,这些类型中的任何一种都可以在单行 @typedef 中使用 TypeScript 语法声明:

¥Of course, any of these types can be declared using TypeScript syntax in a single-line @typedef:

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

@template

你可以使用 @template 标记声明类型参数。这使你可以创建泛型的函数、类或类型:

¥You can declare type parameters with the @template tag. This lets you make functions, classes, or types that are generic:

js
/**
 
* @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({});
Try

使用逗号或多个标签来声明多个类型参数:

¥Use comma or multiple tags to declare multiple type parameters:

js
/**
* @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:

js
/**
 
* @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

最后,你可以为类型参数指定默认值:

¥Finally, you can specify a default for a type parameter:

js
/** @template [T=object] */
class Cache {
/** @param {T} initial */
constructor(initial) {
}
}
let c = new Cache()
Try

@satisfies

@satisfies 提供对 TypeScript 中后缀 运算符 satisfies 的访问。Satisfies 用于声明某个值实现了某种类型,但不影响该值的类型。

¥@satisfies provides access to the postfix operator satisfies in TypeScript. Satisfies is used to declare that a value implements a type but does not affect the type of the value.

js
// @ts-check
/**
 
* @typedef {"hello world" | "Hello, world"} WelcomeMessage
*/
 
/** @satisfies {WelcomeMessage} */
const message = "hello world"
const message: "hello world"
 
/** @satisfies {WelcomeMessage} */
Type '"Hello world!"' does not satisfy the expected type 'WelcomeMessage'.1360Type '"Hello world!"' does not satisfy the expected type 'WelcomeMessage'.
const failingMessage = "Hello world!"
 
/** @type {WelcomeMessage} */
const messageUsingType = "hello world"
const messageUsingType: WelcomeMessage
Try

¥Classes

类可以声明为 ES6 类。

¥Classes can be declared as ES6 classes.

js
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);
Try

它们也可以声明为构造函数;为此使用 @constructor@this

¥They can also be declared as constructor functions; use @constructor along with @this for this.

属性修饰符

¥Property Modifiers

@public@private@protected 在 TypeScript 中的工作方式与 publicprivateprotected 完全相同:

¥@public, @private, and @protected work exactly like public, private, and protected in TypeScript:

js
// @ts-check
 
class Car {
constructor() {
/** @private */
this.identifier = 100;
}
 
printIdentifier() {
console.log(this.identifier);
}
}
 
const c = new Car();
console.log(c.identifier);
Property 'identifier' is private and only accessible within class 'Car'.2341Property 'identifier' is private and only accessible within class 'Car'.
Try
  • @public 总是隐含的,可以省略,但表示可以从任何地方访问属性。

    ¥@public is always implied and can be left off, but means that a property can be reached from anywhere.

  • @private 表示属性只能在包含类中使用。

    ¥@private means that a property can only be used within the containing class.

  • @protected 表示属性只能在包含类和所有派生子类中使用,但不能在包含类的不同实例上使用。

    ¥@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@protected 在构造函数中不起作用。

¥@public, @private, and @protected do not work in constructor functions.

@readonly

@readonly 修饰符确保只在初始化期间写入属性。

¥The @readonly modifier ensures that a property is only ever written to during initialization.

js
// @ts-check
 
class Car {
constructor() {
/** @readonly */
this.identifier = 100;
}
 
printIdentifier() {
console.log(this.identifier);
}
}
 
const c = new Car();
console.log(c.identifier);
Try

@override

@override 的工作方式与 TypeScript 相同;在覆盖基类方法的方法上使用它:

¥@override works the same way as in TypeScript; use it on methods that override a method from a base class:

js
export class C {
m() { }
}
class D extends C {
/** @override */
m() { }
}
Try

在 tsconfig 中设置 noImplicitOverride: true 以检查覆盖。

¥Set noImplicitOverride: true in tsconfig to check overrides.

@extends

当 JavaScript 类扩展泛型基类时,没有用于传递类型参数的 JavaScript 语法。@extends 标签允许这样:

¥When JavaScript classes extend a generic base class, there is no JavaScript syntax for passing a type argument. The @extends tag allows this:

js
/**
 
* @template T
 
* @extends {Set<T>}
*/
class SortableSet extends Set {
// ...
}
Try

请注意,@extends 仅适用于类。目前,构造函数无法扩展类。

¥Note that @extends only works with classes. Currently, there is no way for a constructor function to extend a class.

@implements

同样,没有用于实现 TypeScript 接口的 JavaScript 语法。@implements 标签就像在 TypeScript 中一样工作:

¥In the same way, there is no JavaScript syntax for implementing a TypeScript interface. The @implements tag works just like in TypeScript:

js
/** @implements {Print} */
class TextBook {
print() {
// TODO
}
}
Try

@constructor

编译器根据 this-property 赋值推断构造函数,但如果添加 @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:

js
/**
 
* @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 = new C(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

注意:错误消息仅显示在启用了 一个 JSConfigcheckJs 的 JS 代码库中。

¥Note: Error messages only show up in JS codebases with a JSConfig and checkJs enabled.

对于 @constructorthis 在构造函数 C 中进行检查,因此你将获得 initialize 方法的建议,如果你向它传递一个数字,则会出现错误。如果你调用 C 而不是构造它,你的编辑器也可能会显示警告。

¥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.

不幸的是,这意味着同样可调用的构造函数不能使用 @constructor

¥Unfortunately, this means that constructor functions that are also callable cannot use @constructor.

@this

当编译器有一些上下文可以使用时,它通常可以找出 this 的类型。如果没有,你可以使用 @this 显式指定 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:

js
/**
 
* @this {HTMLElement}
 
* @param {*} e
*/
function callbackForLater(e) {
this.clientHeight = parseInt(e); // should be fine!
}
Try

文档

¥Documentation

@deprecated

当一个函数、方法或属性被弃用时,你可以通过用 /** @deprecated */ JSDoc 注释标记它来让用户知道。该信息显示在完成列表中,并作为编辑可以专门处理的建议诊断。在 VS Code 等编辑器中,不推荐使用的值通常以删除线样式 like this 显示。

¥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.

js
/** @deprecated */
const apiV1 = {};
const apiV2 = {};
 
apiV;
   
 
 
Try

@see

@see 允许你链接到程序中的其他名称:

¥@see lets you link to other names in your program:

ts
type Box<T> = { t: T }
/** @see Box for implementation details */
type Boxify<T> = { [K in keyof T]: Box<T> };
Try

一些编辑器会将 Box 变成一个链接,以便于跳转和返回。

¥Some editors will turn Box into a link to make it easy to jump there and back.

@link@see 类似,只是它可以在其他标签内使用:

¥@link is like @see, except that it can be used inside other tags:

ts
type Box<T> = { t: T }
/** @returns A {@link Box} containing the parameter. */
function box<U>(u: U): Box<U> {
return { t: u };
}
Try

其他

¥Other

@enum

@enum 标记允许你创建一个对象字面,其成员都是指定类型。与 JavaScript 中的大多数对象字面不同,它不允许其他成员。@enum 旨在与 Google Closure 的 @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.

js
/** @enum {number} */
const JSDocState = {
BeginningOfLine: 0,
SawAsterisk: 1,
SavingComments: 2,
};
 
JSDocState.SawAsterisk;
Try

请注意,@enum 与 TypeScript 的 enum 截然不同,而且简单得多。然而,与 TypeScript 的枚举不同,@enum 可以是任何类型:

¥Note that @enum is quite different from, and much simpler than, TypeScript’s enum. However, unlike TypeScript’s enums, @enum can have any type:

js
/** @enum {function(number): number} */
const MathFuncs = {
add1: (n) => n + 1,
id: (n) => -n,
sub1: (n) => n - 1,
};
 
MathFuncs.add1;
Try

@author

你可以使用 @author 指定项目的作者:

¥You can specify the author of an item with @author:

ts
/**
 
* Welcome to awesome.ts
 
* @author Ian Awesome <i.am.awesome@example.com>
*/
Try

请记住用尖括号将电邮地址括起来。否则,@example 将被解析为新标签。

¥Remember to surround the email address with angle brackets. Otherwise, @example will be parsed as a new tag.

其他支持的模式

¥Other supported patterns

js
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();
}
Try

不支持的模式

¥Unsupported patterns

对象字面类型中属性类型的后缀等于未指定可选属性:

¥Postfix equals on a property type in an object literal type doesn’t specify an optional property:

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

可空类型只有在 strictNullChecks 打开时才有意义:

¥Nullable types only have meaning if strictNullChecks is on:

js
/**
 
* @type {?number}
 
* With strictNullChecks: true -- number | null
 
* With strictNullChecks: false -- number
*/
var nullable;
Try

TypeScript 原生语法是联合类型:

¥The TypeScript-native syntax is a union type:

js
/**
 
* @type {number | null}
 
* With strictNullChecks: true -- number | null
 
* With strictNullChecks: false -- number
*/
var unionNullable;
Try

不可为 null 的类型没有意义,并被视为它们的基础类型:

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

js
/**
 
* @type {!number}
 
* Just has type number
*/
var normal;
Try

与 JSDoc 的类型系统不同,TypeScript 只允许你将类型标记为包含或不包含 null。没有明确的不可空性 - 如果启用了 strictNullChecks,则 number 不可空。如果关闭,则 number 可为空。

¥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 会忽略任何不受支持的 JSDoc 标签。

¥TypeScript ignores any unsupported JSDoc tags.

以下标签有未解决的问题来支持它们:

¥The following tags have open issues to support them: