Skip to content
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待

JSDoc 参考

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

注意:

  • 任何未在下面明确列出的标签(例如 @async)尚未支持。
  • TypeScript 文件中仅支持文档标签。其余标签仅在 JavaScript 文件中支持。

类型

文档

文档标签在 TypeScript 和 JavaScript 中都有效。

其他

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

注意: 你可以使用演练场来探索 JSDoc 支持

类型

@type

你可以使用 @type 标签引用类型。类型可以是:

  1. 原始类型,如 stringnumber
  2. 在 TypeScript 声明中声明的类型,无论是全局的还是导入的。
  3. 在 JSDoc @typedef 标签中声明的类型。

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

js
/**
 * @type {string}
 */
var 
s
;
/** @type {Window} */ var
win
;
/** @type {PromiseLike<string>} */ var
promisedString
;
// 你可以使用 DOM 属性指定一个 HTML 元素 /** @type {HTMLElement} */ var
myElement
=
document
.
querySelector
(selector);
element
.
dataset
.
myData
= "";
Try

@type 可以指定联合类型——例如,某物可以是字符串或布尔值。

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

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

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

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

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

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

js
/**
 * 一个类似映射的对象,将任意的 `string` 属性映射到 `number`。
 *
 * @type {Object.<string, number>}
 */
var 
stringToNumber
;
/** @type {Object.<number, object>} */ var
arrayLike
;
Try

前两种类型分别等价于 TypeScript 类型 { [x: string]: number }{ [x: number]: any }。编译器理解这两种语法。

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

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

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

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

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

js
/**
 * @type {*} - 可以是 'any' 类型
 */
var 
star
;
/** * @type {?} - 未知类型(同 'any') */ var
question
;
Try

类型断言

TypeScript 借鉴了 Google Closure 的断言语法。 这允许你在任何带括号的表达式之前添加一个 @type 标签来将类型转换为其他类型。

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

你甚至可以像 TypeScript 一样断言为 const

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

导入类型

你可以使用导入类型从其他文件导入声明。 这种语法是 TypeScript 特有的,与 JSDoc 标准不同:

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

如果你不知道类型,或者如果类型很大而输入麻烦,可以使用导入类型从模块中获取值的类型:

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

@import

@import 标签允许我们引用其他文件中的导出。

js
/**
 * @import {Pet} from "./types"
 */

/**
 * @type {Pet}
 */
var 
myPet
;
myPet
.
name
;
Try

这些标签实际上并不在运行时导入文件,它们引入作用域的符号只能在 JSDoc 注释中用于类型检查。

js
// @filename: dog.js
export class 
Dog
{
woof
() {
console
.
log
("Woof!");
} } // @filename: main.js /** @import { Dog } from "./dog.js" */ const
d
= new
Dog
(); // 错误!
Try

@param@returns

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

js
// 参数可以用多种语法形式声明
/**
 * @param {string}  p1 - 一个字符串参数。
 * @param {string=} p2 - 一个可选参数(Google Closure 语法)
 * @param {string} [p3] - 另一个可选参数(JSDoc 语法)。
 * @param {string} [p4="test"] - 一个带有默认值的可选参数
 * @returns {string} 这是结果
 */
function 
stringsStringStrings
(
p1
,
p2
,
p3
,
p4
) {
// TODO }
Try

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

js
/**
 * @return {PromiseLike<string>}
 */
function 
ps
() {}
/** * @returns {{ a: string, b: number }} - 可以使用 '@returns' 以及 '@return' */ function
ab
() {}
Try

@typedef@callback@param

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

js
/**
 * @typedef {Object} SpecialType - 创建一个名为 'SpecialType' 的新类型
 * @property {string} prop1 - SpecialType 的一个字符串属性
 * @property {number} prop2 - SpecialType 的一个数字属性
 * @property {number=} prop3 - SpecialType 的一个可选数字属性
 * @prop {number} [prop4] - SpecialType 的一个可选数字属性
 * @prop {number} [prop5=42] - 带有默认值的 SpecialType 可选数字属性
 */

/** @type {SpecialType} */
var 
specialTypeObject
;
specialTypeObject
.
prop3
;
Try

你可以在第一行使用 objectObject

js
/**
 * @typedef {object} SpecialType1 - 创建一个名为 'SpecialType1' 的新类型
 * @property {string} prop1 - SpecialType1 的一个字符串属性
 * @property {number} prop2 - SpecialType1 的一个数字属性
 * @property {number=} prop3 - SpecialType1 的一个可选数字属性
 */

/** @type {SpecialType1} */
var 
specialTypeObject1
;
Try

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

js
/**
 * @param {Object} options - 形状与上面的 SpecialType 相同
 * @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,但它指定的是函数类型而不是对象类型:

js
/**
 * @callback Predicate
 * @param {string} data
 * @param {number} [index]
 * @returns {boolean}
 */

/** @type {Predicate} */
const 
ok
= (
s
) => !(
s
.
length
% 2);
Try

当然,所有这些类型都可以在单行 @typedef 中使用 TypeScript 语法声明:

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

@template

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

js
/**
 * @template T
 * @param {T} x - 一个泛型参数,会传递到返回类型
 * @returns {T}
 */
function 
id
(
x
) {
return
x
;
} const
a
=
id
("string");
const
b
=
id
(123);
const
c
=
id
({});
Try

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

js
/**
 * @template T,U,V
 * @template W,X
 */

你也可以在类型参数名称之前指定类型约束。 列表中只有第一个类型参数会被约束:

js
/**
 * @template {string} K - K 必须是字符串或字符串字面量
 * @template {{ serious(): string }} Seriousalizable - 必须有一个 serious 方法
 * @param {K} key
 * @param {Seriousalizable} object
 */
function 
seriousalize
(
key
,
object
) {
// ???? }
Try

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

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

@satisfies

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

js
// @ts-check
/**
 * @typedef {"hello world" | "Hello, world"} WelcomeMessage
 */

/** @satisfies {WelcomeMessage} */
const 
message
= "hello world"
/** @satisfies {WelcomeMessage} */
Type '"Hello world!"' does not satisfy the expected type 'WelcomeMessage'.
const
failingMessage
= "Hello world!"
/** @type {WelcomeMessage} */ const
messageUsingType
= "hello world"
Try

类可以声明为 ES6 类。

js
class 
C
{
/** * @param {number} data */ constructor(
data
) {
// 属性类型可以被推断 this.
name
= "foo";
// 或者显式设置 /** @type {string | null} */ this.
title
= null;
// 或者仅注释,如果它们在其他地方设置 /** @type {number} */ this.
size
;
this.
initialize
(
data
); // 应该报错,初始化器期望一个字符串
} /** * @param {string} s */
initialize
= function (
s
) {
this.
size
=
s
.
length
;
}; } var
c
= new
C
(0);
// C 应该只能通过 new 调用,但因为它是 JavaScript,这是允许的, // 并被视为 'any'。 var
result
=
C
(1);
Try

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

属性修饰符

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

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'.
Try
  • @public 总是隐含的,可以省略,但意味着属性可以从任何地方访问。
  • @private 意味着属性只能在包含它的类中使用。
  • @protected 意味着属性只能在包含它的类以及所有派生类中使用,但不能在包含它的类的不相似实例上使用。

@public@private@protected 在构造函数中不起作用。

@readonly

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

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 中相同;在覆盖基类方法的方法上使用它:

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

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

@extends

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

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

注意 @extends 只适用于类。目前,没有一种方法可以使构造函数扩展一个类。

@implements

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

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

@constructor

编译器根据 this 属性的赋值来推断构造函数,但如果你添加一个 @constructor 标签,可以使检查更严格,建议更好:

js
/**
 * @constructor
 * @param {number} data
 */
function 
C
(
data
) {
// 属性类型可以被推断 this.
name
= "foo";
// 或者显式设置 /** @type {string | null} */ this.
title
= null;
// 或者仅注释,如果它们在其他地方设置 /** @type {number} */ this.
size
;
this.
initialize
(data);
Argument 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'?
Try

注意:错误消息只会在启用 JSConfigcheckJs 的 JS 代码库中显示。

使用 @constructorthis 在构造函数 C 内部会被检查,因此你会得到 initialize 方法的建议,如果你传递一个数字给它,会出现错误。如果你调用 C 而不是构造它,编辑器也可能会显示警告。

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

@this

当编译器有一些上下文可以处理时,它通常可以推断出 this 的类型。当它不能时,你可以用 @this 显式指定 this 的类型:

js
/**
 * @this {HTMLElement}
 * @param {*} e
 */
function 
callbackForLater
(
e
) {
this.
clientHeight
=
parseInt
(
e
); // 应该没问题!
}
Try

文档

@deprecated

当一个函数、方法或属性被弃用时,你可以通过用 /** @deprecated */ JSDoc 注释标记来让用户知道。该信息会显示在补全列表中,并作为建议诊断信息,编辑器可以特殊处理。在像 VS Code 这样的编辑器中,弃用的值通常以删除线样式显示 像这样

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

@see

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

ts
type 
Box
<
T
> = {
t
:
T
}
/** @see Box 了解实现细节 */ type
Boxify
<
T
> = { [
K
in keyof
T
]:
Box
<
T
> };
Try

一些编辑器会将 Box 转换为链接,使其易于跳转和返回。

@link 类似于 @see,但它可以在其他标签内部使用:

ts
type 
Box
<
T
> = {
t
:
T
}
/** @returns 一个包含参数的 {@link Box}。 */ function
box
<
U
>(
u
:
U
):
Box
<
U
> {
return {
t
:
u
};
}
Try

你也可以链接一个属性:

ts
type 
Pet
= {
name
: string
hello
: () => string
} /** * 注意:你应该实现 Pet 的 {@link Pet.hello} 方法。 */ function
hello
(
p
:
Pet
) {
p
.
hello
()
}
Try

或带有可选名称:

ts
type 
Pet
= {
name
: string
hello
: () => string
} /** * 注意:你应该实现 Pet 的 {@link Pet.hello | hello} 方法。 */ function
hello
(
p
:
Pet
) {
p
.
hello
()
}
Try

其他

@enum

@enum 标签允许你创建一个对象字面量,其成员都是指定类型。与 JavaScript 中的大多数对象字面量不同,它不允许其他成员。 @enum 旨在与 Google Closure 的 @enum 标签兼容。

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

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

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

@author

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

ts
/**
 * 欢迎使用 awesome.ts
 * @author Ian Awesome <i.am.awesome@example.com>
 */
Try

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

其他支持的模式

js
var 
someObj
= {
/** * @param {string} param1 - 属性赋值上的 JSDoc 也有效 */
x
: function (
param1
) {},
}; /** * 变量赋值上的 JSDoc 也有效 * @return {Window} */ let
someFunc
= function () {};
/** * 以及类方法 * @param {string} greeting 要使用的问候语 */
Foo
.
prototype
.
sayHi
= (
greeting
) =>
console
.
log
("Hi!");
/** * 以及箭头函数表达式 * @param {number} x - 一个乘数 */ let
myArrow
= (
x
) =>
x
*
x
;
/** * 这意味着它也适用于 JSX 中的函数组件 * @param {{a: string, b: number}} props - 一些参数 */ var
fc
= (
props
) => <
div
>{
props
.
a
.
charAt
(0)}</
div
>;
/** * 参数可以是一个类构造函数,使用 Google Closure 语法。 * * @param {{new(...args: any[]): object}} C - 要注册的类 */ function
registerClass
(
C
) {}
/** * @param {...string} p1 - 一个 'rest' 参数(数组),包含字符串。(被视为 'any') */ function
fn10
(
p1
) {}
/** * @param {...string} p1 - 一个 'rest' 参数(数组),包含字符串。(被视为 'any') */ function
fn9
(
p1
) {
return
p1
.join();
}
Try

不支持的模式

对象字面量类型中属性类型上的后缀等号并不指定可选属性:

js
/**
 * @type {{ a: string, b: number= }}
 */
var 
wrong
;
/** * 而是在属性名称上使用后缀问号: * @type {{ a: string, b?: number }} */ var
right
;
Try

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

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

TypeScript 原生语法是联合类型:

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

非空类型没有意义,仅被视为其原始类型:

js
/**
 * @type {!number}
 * 仅具有类型 number
 */
var 
normal
;
Try

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

不支持的标签

TypeScript 忽略任何不支持的 JSDoc 标签。

以下标签有支持它们的开放问题:

旧版类型同义词

许多常见类型为与旧 JavaScript 代码兼容而赋予了别名。 一些别名与现有类型相同,尽管其中大多数很少使用。 例如,String 被视为 string 的别名。 尽管 String 是 TypeScript 中的一种类型,但旧的 JSDoc 经常用它来表示 string。 此外,在 TypeScript 中,原始类型的大写版本是包装类型——使用它们几乎总是一个错误。 因此,编译器根据旧 JSDoc 中的用法将这些类型视为同义词:

  • String -> string
  • Number -> number
  • Boolean -> boolean
  • Void -> void
  • Undefined -> undefined
  • Null -> null
  • function -> Function
  • array -> Array<any>
  • promise -> Promise<any>
  • Object -> any
  • object -> any

noImplicitAny: true 时,最后四个别名被关闭:

  • objectObject 是内置类型,尽管 Object 很少使用。
  • arraypromise 不是内置类型,但可能在你的程序中的某处声明。