下面的列表概述了在使用 JSDoc 注释在 JavaScript 文件中提供类型信息时当前支持哪些结构。
¥The list below outlines which constructs are currently supported when using JSDoc annotations to provide type information in JavaScript files.
注意:
¥Note:
-
尚不支持任何未在下面明确列出的标签(例如
@async
)。¥Any tags which are not explicitly listed below (such as
@async
) are not yet supported. -
TypeScript 文件中仅支持文档标签。其余标签仅在 JavaScript 文件中受支持。
¥Only documentation tags are supported in TypeScript files. The rest of the tags are only supported in JavaScript files.
类型
¥Types
类
¥Classes
-
属性修饰符
@public
,@private
,@protected
,@readonly
¥Property Modifiers
@public
,@private
,@protected
,@readonly
-
¥
@class
(or@constructor
)
文档
¥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:
-
基础类型,如
string
或number
。¥Primitive, like
string
ornumber
. -
在 TypeScript 声明中声明,全局或导入。
¥Declared in a TypeScript declaration, either global or imported.
-
在 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.
jsTry
/*** @type {string}*/vars ;/** @type {Window} */varwin ;/** @type {PromiseLike<string>} */varpromisedString ;// You can specify an HTML Element with DOM properties/** @type {HTMLElement} */varmyElement =document .querySelector (selector );element .dataset .myData = "";
@type
可以指定联合类型 - 例如,某些内容可以是字符串或布尔值。
¥@type
can specify a union type — for example, something can be either a string or a boolean.
jsTry
/*** @type {string | boolean}*/varsb ;
你可以使用多种语法指定数组类型:
¥You can specify array types using a variety of syntaxes:
jsTry
/** @type {number[]} */varns ;/** @type {Array.<number>} */varjsdoc ;/** @type {Array<number>} */varnas ;
你还可以指定对象字面类型。例如,具有属性 ‘a’(字符串)和 ‘b’(数字)的对象使用以下语法:
¥You can also specify object literal types. For example, an object with properties ‘a’ (string) and ‘b’ (number) uses the following syntax:
jsTry
/** @type {{ a: string, b: number }} */varvar9 ;
你可以使用标准 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.
jsTry
/*** A map-like object that maps arbitrary `string` properties to `number`s.* * @type {Object.<string, number>}*/varstringToNumber ;/** @type {Object.<number, object>} */vararrayLike ;
上述两种类型相当于 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:
jsTry
/** @type {function(string, boolean): number} Closure syntax */varsbn ;/** @type {(s: string, b: boolean) => number} TypeScript syntax */varsbn2 ;
或者你可以只使用未指定的 Function
类型:
¥Or you can just use the unspecified Function
type:
jsTry
/** @type {Function} */varfn7 ;/** @type {function} */varfn6 ;
Closure 的其他类型也可以工作:
¥Other types from Closure also work:
jsTry
/*** @type {*} - can be 'any' type*/varstar ;/*** @type {?} - unknown type (same as 'any')*/varquestion ;
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.
jsTry
/*** @type {number | string}*/varnumberOrString =Math .random () < 0.5 ? "hello" : 100;vartypeAssertedNumber = /** @type {number} */ (numberOrString );
你甚至可以像 TypeScript 一样转换为 const
:
¥You can even cast to const
just like TypeScript:
jsTry
letone = /** @type {const} */(1);
导入类型
¥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:
jsTry
// @filename: types.d.tsexport typePet = {name : string,};// @filename: main.js/*** @param {import("./types").Pet} p*/functionwalk (p ) {console .log (`Walking ${p .name }...`);}
导入类型可以在类型别名声明中使用:
¥import types can be used in type alias declarations:
jsTry
/*** @typedef {import("./types").Pet} Pet*//*** @type {Pet}*/varmyPet ;myPet .name ;
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:
jsTry
/*** @type {typeof import("./accounts").userAccount}*/varx =require ("./accounts").userAccount ;
@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:
jsTry
// 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*/functionstringsStringStrings (p1 ,p2 ,p3 ,p4 ) {// TODO}
同样,对于函数的返回类型:
¥Likewise, for the return type of a function:
jsTry
/*** @return {PromiseLike<string>}*/functionps () {}/*** @returns {{ a: string, b: number }} - May use '@returns' as well as '@return'*/functionab () {}
@typedef
、@callback
和 @param
¥@typedef
, @callback
, and @param
你可以使用 @typedef
定义复杂类型。类似的语法适用于 @param
。
¥You can define complex types with @typedef
.
Similar syntax works with @param
.
jsTry
/*** @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} */varspecialTypeObject ;specialTypeObject .prop3 ;
你可以在第一行使用 object
或 Object
。
¥You can use either object
or Object
on the first line.
jsTry
/*** @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} */varspecialTypeObject1 ;
@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:
jsTry
/*** @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]*/functionspecial (options ) {return (options .prop4 || 1001) +options .prop5 ;}
@callback
与 @typedef
类似,但它指定的是函数类型而不是对象类型:
¥@callback
is similar to @typedef
, but it specifies a function type instead of an object type:
jsTry
/*** @callback Predicate* @param {string} data* @param {number} [index]* @returns {boolean}*//** @type {Predicate} */constok = (s ) => !(s .length % 2);
当然,这些类型中的任何一种都可以在单行 @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:
jsTry
/*** @template T* @param {T} x - A generic parameter that flows through to the return type* @returns {T}*/functionid (x ) {returnx ;}consta =id ("string");constb =id (123);constc =id ({});
使用逗号或多个标签来声明多个类型参数:
¥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:
jsTry
/*** @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*/functionseriousalize (key ,object ) {// ????}
最后,你可以为类型参数指定默认值:
¥Finally, you can specify a default for a type parameter:
jsTry
/** @template [T=object] */classCache {/** @param {T} initial */constructor(initial ) {}}letc = newCache ()
@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.
jsTry
// @ts-check/*** @typedef {"hello world" | "Hello, world"} WelcomeMessage*//** @satisfies {WelcomeMessage} */constmessage = "hello world"/** @Type '"Hello world!"' does not satisfy the expected type 'WelcomeMessage'.1360Type '"Hello world!"' does not satisfy the expected type 'WelcomeMessage'.satisfies {WelcomeMessage} */constfailingMessage = "Hello world!"/** @type {WelcomeMessage} */constmessageUsingType = "hello world"
类
¥Classes
类可以声明为 ES6 类。
¥Classes can be declared as ES6 classes.
jsTry
classC {/*** @param {number} data*/constructor(data ) {// property types can be inferredthis.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 ;};}varc = newC (0);// C should only be called with new, but// because it is JavaScript, this is allowed and// considered an 'any'.varresult =C (1);
它们也可以声明为构造函数;为此使用 @constructor
和 @this
。
¥They can also be declared as constructor functions; use @constructor
along with @this
for this.
属性修饰符
¥Property Modifiers
@public
、@private
和 @protected
在 TypeScript 中的工作方式与 public
、private
和 protected
完全相同:
¥@public
, @private
, and @protected
work exactly like public
, private
, and protected
in TypeScript:
jsTry
// @ts-checkclassCar {constructor() {/** @private */this.identifier = 100;}printIdentifier () {console .log (this.identifier );}}constc = newCar ();Property 'identifier' is private and only accessible within class 'Car'.2341Property 'identifier' is private and only accessible within class 'Car'.console .log (c .); identifier
-
@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.
jsTry
// @ts-checkclassCar {constructor() {/** @readonly */this.identifier = 100;}printIdentifier () {console .log (this.identifier );}}constc = newCar ();console .log (c .identifier );
@override
@override
的工作方式与 TypeScript 相同;在覆盖基类方法的方法上使用它:
¥@override
works the same way as in TypeScript; use it on methods that override a method from a base class:
jsTry
export classC {m () { }}classD extendsC {/** @override */m () { }}
在 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:
jsTry
/*** @template T* @extends {Set<T>}*/classSortableSet extendsSet {// ...}
请注意,@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:
jsTry
/** @implements {Print} */classTextBook {// TODO}}
@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:
jsTry
/*** @constructor* @param {number} data*/functionC (data ) {// property types can be inferredthis.name = "foo";// or set explicitly/** @type {string | null} */this.title = null;// or simply annotated, if they're set elsewhere/** @type {number} */this.size ;this.Argument of type 'number' is not assignable to parameter of type 'string'.2345Argument of type 'number' is not assignable to parameter of type 'string'.initialize (); data }/*** @param {string} s*/C .prototype .initialize = function (s ) {this.size =s .length ;};varc = newC (0);c .size ;varValue 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'?result =C (1);
注意:错误消息仅显示在启用了 一个 JSConfig 和
checkJs
的 JS 代码库中。¥Note: Error messages only show up in JS codebases with a JSConfig and
checkJs
enabled.
对于 @constructor
,this
在构造函数 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
:
jsTry
/*** @this {HTMLElement}* @param {*} e*/functioncallbackForLater (e ) {this.clientHeight =parseInt (e ); // should be fine!}
文档
¥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.
jsTry
/** @deprecated */constapiV1 = {};constapiV2 = {};apiV ;
@see
@see
允许你链接到程序中的其他名称:
¥@see
lets you link to other names in your program:
tsTry
typeBox <T > = {t :T }/** @see Box for implementation details */typeBoxify <T > = { [K in keyofT ]:Box <T > };
一些编辑器会将 Box
变成一个链接,以便于跳转和返回。
¥Some editors will turn Box
into a link to make it easy to jump there and back.
@link
@link
与 @see
类似,只是它可以在其他标签内使用:
¥@link
is like @see
, except that it can be used inside other tags:
tsTry
typeBox <T > = {t :T }/** @returns A {@link Box} containing the parameter. */functionbox <U >(u :U ):Box <U > {return {t :u };}
你还可以链接属性:
¥You can also link a property:
tsTry
typePet = {name : stringhello : () => string}/*** Note: you should implement the {@link Pet.hello} method of Pet.*/functionhello (p :Pet ) {p .hello ()}
或者使用可选名称:
¥Or with an optional name:
tsTry
typePet = {name : stringhello : () => string}/*** Note: you should implement the {@link Pet.hello | hello} method of Pet.*/functionhello (p :Pet ) {p .hello ()}
其他
¥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.
jsTry
/** @enum {number} */constJSDocState = {BeginningOfLine : 0,SawAsterisk : 1,SavingComments : 2,};JSDocState .SawAsterisk ;
请注意,@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:
jsTry
/** @enum {function(number): number} */constMathFuncs = {add1 : (n ) =>n + 1,id : (n ) => -n ,sub1 : (n ) =>n - 1,};MathFuncs .add1 ;
@author
你可以使用 @author
指定项目的作者:
¥You can specify the author of an item with @author
:
tsTry
/*** Welcome to awesome.ts* @author Ian Awesome <i.am.awesome@example.com>*/
请记住用尖括号将电邮地址括起来。否则,@example
将被解析为新标签。
¥Remember to surround the email address with angle brackets.
Otherwise, @example
will be parsed as a new tag.
其他支持的模式
¥Other supported patterns
jsTry
varsomeObj = {/*** @param {string} param1 - JSDocs on property assignments work*/x : function (param1 ) {},};/*** As do jsdocs on variable assignments* @return {Window}*/letsomeFunc = 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*/letmyArrow = (x ) =>x *x ;/*** Which means it works for function components in JSX too* @param {{a: string, b: number}} props - Some param*/varfc = (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*/functionregisterClass (C ) {}/*** @param {...string} p1 - A 'rest' arg (array) of strings. (treated as 'any')*/functionfn10 (p1 ) {}/*** @param {...string} p1 - A 'rest' arg (array) of strings. (treated as 'any')*/functionfn9 (p1 ) {returnp1 .join ();}
不支持的模式
¥Unsupported patterns
对象字面类型中属性类型的后缀等于未指定可选属性:
¥Postfix equals on a property type in an object literal type doesn’t specify an optional property:
jsTry
/*** @type {{ a: string, b: number= }}*/varwrong ;/*** Use postfix question on the property name instead:* @type {{ a: string, b?: number }}*/varright ;
可空类型只有在 strictNullChecks
打开时才有意义:
¥Nullable types only have meaning if strictNullChecks
is on:
jsTry
/*** @type {?number}* With strictNullChecks: true -- number | null* With strictNullChecks: false -- number*/varnullable ;
TypeScript 原生语法是联合类型:
¥The TypeScript-native syntax is a union type:
jsTry
/*** @type {number | null}* With strictNullChecks: true -- number | null* With strictNullChecks: false -- number*/varunionNullable ;
不可为 null 的类型没有意义,并被视为它们的基础类型:
¥Non-nullable types have no meaning and are treated just as their original type:
jsTry
/*** @type {!number}* Just has type number*/varnormal ;
与 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:
-
@memberof
(问题 #7237)¥
@memberof
(issue #7237) -
@yields
(问题 #23857)¥
@yields
(issue #23857) -
@member
(问题 #56674)¥
@member
(issue #56674)
旧版类型同义词
¥Legacy type synonyms
为了与旧的 JavaScript 代码兼容,许多常见类型都被赋予了别名。一些别名与现有类型相同,尽管大多数别名很少使用。例如,String
被视为 string
的别名。尽管 String
是 TypeScript 中的一种类型,但旧的 JSDoc 经常使用它来表示 string
。此外,在 TypeScript 中,原始类型的大写版本是封装器类型 - 几乎总是使用错误。因此,编译器根据旧 JSDoc 中的用法将这些类型视为同义词:
¥A number of common types are given aliases for compatibility with old JavaScript code.
Some of the aliases are the same as existing types, although most of those are rarely used.
For example, String
is treated as an alias for string
.
Even though String
is a type in TypeScript, old JSDoc often uses it to mean string
.
Besides, in TypeScript, the capitalized versions of primitive types are wrapper types — almost always a mistake to use.
So the compiler treats these types as synonyms based on usage in old 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
时,最后四个别名被关闭:
¥The last four aliases are turned off when noImplicitAny: true
:
-
object
和Object
是内置类型,尽管Object
很少使用。¥
object
andObject
are built-in types, althoughObject
is rarely used. -
array
和promise
不是内置的,但可能在程序中的某个地方声明。¥
array
andpromise
are not built-in, but might be declared somewhere in your program.