引言:为什么文档是投资,而非浪费时间
每个开发者都遇到过这种情况:一个月后回到自己的代码,却很难记起某个参数的用途。更不用说试图理解你项目的新团队成员了。为 TypeScript 项目编写高质量的文档不仅仅是一个不错的附加功能,而是一个至关重要的元素,它能加速入职流程、减少错误数量,并使代码更易于维护。
TypeScript 作为 JavaScript 的超集,提供了强大的类型系统。然而,类型本身并不总能回答“为什么”这个问题。文档填补了这一空白。在本文中,我们将介绍完整的流程:从选择注释风格到生成静态文档网站。
1. 基础:JSDoc、TSDoc 和 TypeScript
为 TypeScript 代码编写文档,历史上形成了两个主要标准:JSDoc 和 TSDoc。JSDoc 是来自 JavaScript 世界的经典格式。TSDoc 是更现代的标准,专门为 TypeScript 优化。两种方法都使用 /** ... */ 格式的注释。
让我们看一个使用 JSDoc 的基本示例:
/** * 计算两个数字的和。 * @param a - 第一个加数 * @param b - 第二个加数 * @returns a 和 b 的和 */function add(a: number, b: number): number { return a + b;}以下是使用 TSDoc 风格并带有 @param 和 @returns 标签的样子:
/** * 计算两个数字的和。 * @param a - 第一个加数 * @param b - 第二个加数 * @returns a 和 b 的和 */function add(a: number, b: number): number { return a + b;}差异很小,但 TSDoc 增加了对 TypeScript 特定构造的支持,例如泛型和条件类型。
1.1 记录接口和类型
应特别注意接口和类型。它们是 TypeScript 项目的“骨架”。以下是一个文档完善的接口示例:
/** * 表示系统中的用户。 */interface User { /** 用户的唯一标识符 */ id: string; /** 用户的全名 */ name: string; /** 电子邮件地址(必须唯一) */ email: string; /** 上次登录系统的日期(可选) */ lastLogin?: Date; /** 用户在系统中的角色 */ role: 'admin' | 'user' | 'moderator';}请注意:接口的每个参数都有自己的 /** ... */ 注释。这允许 IDE(例如 VS Code)在使用此接口时显示提示。
2. 高级技巧:泛型和条件类型
TypeScript 以其类型系统而闻名,文档应反映其复杂性。这尤其适用于泛型和条件类型。
让我们看一个带有文档的泛型示例:
/** * 创建一个包含单个类型为 T 的元素的数组。 * @template T - 将要放入数组的元素类型 * @param item - 要包装的元素 * @returns 包含传入元素的数组 */function wrapInArray<T>(item: T): T[] { return [item];}@template 标签明确指出了 T 的含义。当有多个泛型或它们具有复杂关系时,这尤其有用。
对于条件类型,文档变得更加重要。示例:
/** * 如果传入的是 Promise,则提取 Promise 中的值类型。 * 否则返回原始类型。 * @template T - 可能是 Promise 也可能不是的类型 * @example * // 对于 Promise<number> 返回 number * type Result = UnwrapPromise<Promise<number>>; // number