JSDoc 參考

以下列表概述了在 JavaScript 檔案中使用 JSDoc 註釋來提供型別資訊時,當前支援的結構。

注意

  • 以下未明確列出的任何標籤(例如 @async)目前均不受支援。
  • TypeScript 檔案中僅支援文件類標籤。其餘標籤僅在 JavaScript 檔案中受支援。

型別

類 (Classes)

文件

文件標籤在 TypeScript 和 JavaScript 中均可使用。

其他

其含義通常與 jsdoc.app 給出的標籤含義相同或為其超集。下文程式碼描述了差異並給出了每個標籤的使用示例。

注意: 您可以使用 演練場(Playground)來探索 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;
 
// You can specify an HTML Element with DOM properties
/** @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

您可以使用字串和數字索引簽名來指定類對映(map-like)和類陣列(array-like)物件,使用標準的 JSDoc 語法或 TypeScript 語法均可。

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 }。編譯器能夠理解這兩種語法。

您可以使用 TypeScript 或 Google Closure 語法來指定函式型別。

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

或者,您也可以直接使用未指定的 Function 型別。

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

來自 Closure 的其他型別同樣適用。

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

型別轉換(Casts)

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

匯入型別(Import types)

您可以使用匯入型別從其他檔案匯入宣告。此語法是 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(); // error!
Try

@param@returns

@param 使用與 @type 相同的型別語法,但增加了一個引數名。引數也可以透過將名稱括在方括號中來宣告為可選。

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

同樣,對於函式的返回型別:

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 定義複雜型別。類似的語法也適用於 @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

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 允許為一次性的型別規範使用類似的語法。注意,巢狀屬性名稱必須以引數名作為字首。

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 類似,但它指定的是函式型別而非物件型別。

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

當然,任何這些型別都可以使用 TypeScript 語法在單行的 @typedef 中宣告。

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

@template

您可以使用 @template 標籤宣告型別引數。這使您可以建立泛型的函式、類或型別。

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

使用逗號或多個標籤來宣告多個型別引數。

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

您也可以在型別引數名稱前指定型別約束。列表中只有第一個型別引數可以被約束。

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

最後,您可以為型別引數指定預設值。

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"
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

類可以宣告為 ES6 類。

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

屬性修飾符

@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'.2341Property '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

同樣,JavaScript 中沒有實現 TypeScript 介面的語法。@implements 標籤的使用方式與 TypeScript 中完全一致。

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

@constructor

編譯器會根據 this 屬性的賦值來推斷建構函式,但如果您新增 @constructor 標籤,可以使檢查更嚴格,並獲得更好的建議。

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 程式碼庫中顯示。

使用 @constructor 後,會在建構函式 C 內部檢查 this,因此您將獲得有關 initialize 方法的建議;如果您傳入一個數字,則會收到錯誤。如果呼叫 C 而不是構造它,您的編輯器也可能會顯示警告。

遺憾的是,這意味著既可構造又可呼叫的建構函式無法使用 @constructor

@this

編譯器通常可以在有上下文的情況下推斷出 this 的型別。在沒有上下文時,您可以使用 @this 顯式指定 this 的型別。

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

文件

@deprecated

當函式、方法或屬性被棄用時,您可以透過新增 /** @deprecated */ JSDoc 註釋來告知使用者。該資訊會顯示在補全列表中,並作為編輯器可以特殊處理的建議診斷資訊呈現。在 VS Code 等編輯器中,被棄用的值通常會以刪除線樣式顯示,像這樣

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

@see

@see 允許您連結到程式中的其他名稱。

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

某些編輯器會將 Box 轉換為連結,以便輕鬆跳轉。

@link@see 類似,不同之處在於它可以用於其他標籤內部。

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

您也可以連結屬性。

ts
type Pet = {
name: string
hello: () => string
}
 
/**
* Note: you should implement the {@link Pet.hello} method of Pet.
*/
function hello(p: Pet) {
p.hello()
}
Try

或者使用可選的名稱。

ts
type Pet = {
name: string
hello: () => string
}
 
/**
* Note: you should implement the {@link Pet.hello | hello} method of Pet.
*/
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
/**
* Welcome to awesome.ts
* @author Ian Awesome <i.am.awesome@example.com>
*/
Try

記得用尖括號括起電子郵件地址。否則,@example 將會被解析為一個新標籤。

其他支援的模式

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

不支援的模式

物件字面量型別中屬性型別後的字尾等號並不會指定可選屬性。

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 時才有意義。

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

TypeScript 原生語法是聯合型別。

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

非空型別沒有意義,且被視為其原始型別。

js
/**
* @type {!number}
* Just has type 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 不是內建的,但可能在您的程式中的某處被宣告過。

TypeScript 文件是一個開源專案。透過傳送 Pull Request 來幫助我們完善這些頁面 ❤

此頁面的貢獻者
OTOrta Therox (23)
NSNathan Shively-Sanders (7)
RGRohit Gohri (2)
Rreillylm (1)
RHRemco Haszing (1)
11+

最後更新:2026 年 3 月 27 日