0226. JSDoc 类型注释
- 1. 🎯 本节内容
- 2. 🫧 评价
- 3. 💻 demos.1 - 认识 JSDoc 类型注释
- 4. 💻 demos.2 -
@type标记的经典用法 - 5. 🤔 TS 支持哪些 JSDoc 标记?
- 6. 🤔 JSDoc 与 TS 有什么区别?
- 7. 🔗 引用
1. 🎯 本节内容
- JSDoc 类型注释系统概述
- TS 支持的 JSDoc 标记
- JSDoc 与 TS 的关系和区别
2. 🫧 评价
本节介绍的内容,在官方文档有专门的介绍文档:TS Handbook - JSDoc Reference - 这是在 JS 中渐进引入 TS 类型系统的“桥梁手册”——通过标准 JSDoc 让 .js 文件获得接近 .ts 的类型检查能力。
JSDoc 是 JS 的文档注释标准,TS 扩展了 JSDoc 以支持类型注释,让 JS 项目也能享受类型检查的好处。
- 允许在 JS 中添加类型信息而无需改为
.ts文件 - 配合
@ts-check可以启用类型检查 - 适合渐进式迁移或不想完全转向 TS 的项目
- 编辑器(VS Code)能提供智能提示和类型检查
- 是从 JS 到 TS 的平滑过渡方案
3. 💻 demos.1 - 认识 JSDoc 类型注释
JSDoc 是 JS 的文档注释标准,TS 扩展了它以支持类型信息:
js
/**
* 函数简短描述(第一行)
*
* 详细描述可以占多行
* 可以包含示例代码
*
* @param {类型} 参数名 - 参数描述
* @param {类型} [可选参数名] - 可选参数描述
* @returns {返回类型} 返回值描述
* @throws {错误类型} 抛出错误的描述
* @example
* // 使用示例
* const result = myFunction(arg1, arg2);
*/
function myFunction(param1, param2) {
// 函数实现
}
// 完整示例
/**
* 从数组中查找元素
*
* 使用二分查找算法,要求数组已排序
*
* @template T
* @param {T[]} array - 已排序的数组
* @param {T} target - 要查找的目标值
* @param {function(T, T): number} [compareFn] - 自定义比较函数
* @returns {number} 元素索引,未找到返回 -1
* @throws {TypeError} 如果数组未排序
* @example
* const index = binarySearch([1, 2, 3, 4, 5], 3);
* console.log(index); // 2
*/
function binarySearch(array, target, compareFn) {
// 实现...
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
js
// @ts-check
// 基本类型注解
/**
* 计算两个数的和
* @param {number} a - 第一个数字
* @param {number} b - 第二个数字
* @returns {number} 两数之和
*/
function add(a, b) {
return a + b
}
// 使用时有类型检查
add(1, 2) // ✅ 正确
add('1', 2) // ❌ Error: Argument of type 'string' is not assignable to parameter of type 'number'
// 变量类型注解
/**
* @type {string}
*/
let username = 'Alice'
username = 'Bob' // ✅ 正确
username = 123 // ❌ Error: Type 'number' is not assignable to type 'string'
// 对象类型注解
/**
* @type {{ name: string, age: number }}
*/
const person = {
name: 'Alice',
age: 30,
}
// 数组类型注解
/**
* @type {number[]}
*/
const numbers = [1, 2, 3]
/**
* @type {Array<string>}
*/
const names = ['Alice', 'Bob']
// 联合类型
/**
* @type {string | number}
*/
let value = 'hello'
value = 123 // ✅ 正确
value = true // ❌ Error: Type 'boolean' is not assignable to type 'string | number'
// 可选参数
/**
* @param {string} name
* @param {number} [age] - 可选参数
* @returns {string}
*/
function greet(name, age) {
if (age !== undefined) {
return `Hello, ${name}! You are ${age} years old.`
}
return `Hello, ${name}!`
}
// 默认参数
/**
* @param {string} message
* @param {number} [times=1] - 重复次数
*/
function repeat(message, times = 1) {
return message.repeat(times)
}
// 剩余参数
/**
* @param {...number} numbers
* @returns {number}
*/
function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0)
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
4. 💻 demos.2 - @type 标记的经典用法
使用 @type 标记,可以让我们在指定 JS 模块中为特定变量添加完整类型信息。
背景:比如我们在 1.js、2.js 中定义了一个变量 config1、config2,它表示 webpack 的配置,但是配置字段具体都有哪些,我们往往需要一遍看着官方文档,一遍编写配置,深怕写错。
解决方案:使用 @type 标记来标注变量的类型,让编辑器(比如 VSCode)知道它是 webpack 配置,并在配置字段名称写错的时候,立刻给予我们提示。
具体做法:
js
// @ts-check
/** @type { import("webpack").Configuration } */
const config1 = {
// 1. mode: 设置构建模式
mode: 'development',
// 2. entry: 入口文件
entry: './src/index.js',
// 3. output: 输出配置
output: {
filename: 'bundle.js',
path: __dirname + '/dist',
},
// 4. module: 模块规则配置(loaders)
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
],
},
// 5. plugins: 插件配置
plugins: [],
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
js
const config2 = {
mode111: 'development', // mode 错写为 mode111,不会有任何提示
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: __dirname + '/dist',
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
],
},
plugins: [],
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
json
{
"name": "2",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"packageManager": "pnpm@10.17.1",
"devDependencies": {
"webpack": "^5.102.1"
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
测试结果:
- 错将
mode写为mode111,会立刻报错 - 鼠标悬停到
mode上,会有明确的字段类型定义提示,告诉我们都能填入哪些值 - 如果没有
@type标记,那么写错就是写错了,不会有任何反馈,也不会有任何类型定义的提示



5. 🤔 TS 支持哪些 JSDoc 标记?
直接上官方文档查看:

🫧 评价
- 这些标记主要用于在 JS 模块中,利用 JSDoc 语法来获取 TS 类型系统提供的一些服务,享受 TS 的一些核心优势。
- 部分标记还算好用,比如
@type,但是其它的标记,测试下来 Bug 还是很多的,类型服务的支持效果远没有原生的 TS 来的实在。
6. 🤔 JSDoc 与 TS 有什么区别?
6.1. JSDoc 和 TS 两种写法对比
js
// 示例 1:基本类型声明
// JSDoc 方式
/**
* @param {string} name
* @param {number} age
* @returns {string}
*/
function greetJS(name, age) {
return `Hello, ${name}! You are ${age} years old.`
}
// TS 方式
function greetTS(name: string, age: number): string {
return `Hello, ${name}! You are ${age} years old.`
}
// 示例 2:接口定义
// JSDoc 方式
/**
* @typedef {Object} User
* @property {number} id
* @property {string} name
* @property {string} email
*/
/**
* @param {User} user
*/
function displayUserJS(user) {
console.log(user.name)
}
// TS 方式
interface User {
id: number;
name: string;
email: string;
}
function displayUserTS(user: User): void {
console.log(user.name)
}
// 示例 ...1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
6.2. 优势、劣势分析
- JSDoc 写法的优势:
- 渐进式引入类型检查
- 与现有 JS 项目兼容
- 适合少量个别模块使用
- JSDoc 写法的劣势:
- 语法冗长,写起来麻烦
- 类型表达能力有限
- 缺少一些高级类型特性
- 编辑器支持不如原生 TS(很多类型检查的行为表现会有异常,简单测试了一下,可以说几乎不可用)
- TS 写法的优势:
- 语法简洁,类型声明更自然
- 完整的类型系统支持
- 更好的编辑器支持
- 更强大的类型推断
- 丰富的高级类型特性
- TS 写法的劣势:
- 需要完全重写为 .ts 文件
- 可能影响构建流程
6.3. 决策建议
- 使用 JSDoc 的场景:
- 现有大型 JS 项目
- 不想改变构建流程
- 团队不熟悉 TS
- 需要渐进式迁移
- 库需要同时提供 JS 和类型
- 使用 TS 的场景:
- 新项目
- 需要完整类型系统
- 团队熟悉 TS
- 追求最佳开发体验
- 复杂的类型逻辑
- 混合使用:
- 可以在 TS 项目中导入使用 JSDoc 的 JS 文件
- 也可以在 JS 项目中逐步添加 JSDoc,最终迁移到 TS