name: typescript-jsdoc description: 为TypeScript代码编写高效的JSDoc注释。提供文档格式、策略性放置、最佳实践以及何时需要文档化与何时保持代码自文档化的指导。有助于保持代码清晰度和IDE支持。
TypeScript JSDoc 文档编写
编写高效的JSDoc注释,以增强代码的可维护性,并为开发者和IDE提供有价值的上下文。
核心格式
JSDoc注释以 /** 开始,以 */ 结束,内部行通常以星号开头。标签以 @ 开头,后跟关键字。基本标签包括 @param、@returns、@throws、@example 和 @deprecated。
由于TypeScript代码已包含类型信息,JSDoc应侧重于“为什么”和“如何”,而不是重复类型信息:
/**
* 计算包含税费的总价
* @param basePrice - 税前价格
* @param taxRate - 税率,以小数表示(例如0.08表示8%)
* @returns 应用税费后的总价
*/
function calculateTotal(basePrice: number, taxRate: number): number {
return basePrice * (1 + taxRate);
}
策略性文档层级
将JSDoc的使用视为三个不同的层级,每个层级服务于不同的目的:
必要文档 出现在所有公共API、导出的函数、类和接口上。对于库代码或共享模块,这是必须的。记录实体的作用、重要行为、潜在错误,并在接口不直观时提供使用示例。
澄清性文档 在代码具有非显而易见的行为、实现复杂算法或具有重要副作用时变得有价值。解释签名中不明显的关键行为,警告不寻常的性能特征,或记录重试逻辑、缓存行为或状态管理。这种文档提供了超越类型系统的真正价值。
最小化文档 适用于内部辅助函数、私有方法和简单的工具函数,这些地方的代码是真正自文档化的。即使在这里,一行简短的意图解释也有助于未来的开发者快速理解目的。只有当函数名称和实现立即透明时,才跳过文档。
复杂API的文档结构
对于类和服务,首先在高层级上记录类,然后为公共方法提供详细文档:
/**
* 管理用户认证和会话处理。
*
* 该服务维护一个单例实例,处理所有认证流程,包括登录、注销和令牌刷新。
* 它自动管理令牌过期和续期。
*/
export class AuthenticationService {
/**
* 尝试使用提供的凭据认证用户
* @param credentials - 用户登录信息
* @throws {AuthenticationError} 当凭据无效时
* @throws {NetworkError} 当认证服务器无法访问时
* @example
* ```typescript
* const auth = new AuthenticationService();
* try {
* const session = await auth.login({
* username: 'user@example.com',
* password: 'securepass'
* });
* } catch (error) {
* console.error('登录失败:', error.message);
* }
* ```
*/
async login(credentials: LoginCredentials): Promise<Session> {
// 实现细节
}
}
高级模式
对于泛型函数,JSDoc在提供类型签名单独无法传达的上下文方面表现出色。使用 @template 标签解释类型参数并记录它们如何交互:
/**
* 使用带记忆化的映射函数转换项目数组。
*
* 此函数基于项目标识缓存结果,使其在重复转换相同数据时高效。
* 当数组引用更改时,缓存被清除。
*
* @template T - 输入数组中项目的类型
* @template R - 输出数组中项目的类型
* @param items - 要转换的源数组
* @param mapper - 转换每个项目的函数
* @param keyExtractor - 可选函数,用于生成缓存键
* @returns 转换后的数组,结果可能来自缓存
*/
function memoizedMap<T, R>(
items: T[],
mapper: (item: T) => R,
keyExtractor?: (item: T) => string
): R[] {
// 包含缓存逻辑的实现
}
对于复杂对象参数,使用嵌套参数文档以保持组织清晰:
/**
* 配置应用程序数据库连接
* @param config - 数据库配置选项
* @param config.host - 数据库服务器主机名
* @param config.port - 端口号(默认为5432)
* @param config.ssl - SSL连接设置
* @param config.ssl.required - SSL是否为必需
* @param config.ssl.certificatePath - SSL证书文件路径
* @param config.poolSize - 最大连接池大小(1-100)
*/
function configureDatabase(config: DatabaseConfig): void {
// 配置逻辑
}
何时文档变得冗余
理解JSDoc何时变得冗余同样重要。当TypeScript的类型系统已经讲述了完整的故事,并且函数名称是真正自解释的时候,避免编写文档。像 function isEven(n: number): boolean 这样的实用程序可能不需要JSDoc,除非它有未预料到的边界情况。
同样,避免记录可能改变的实现细节。专注于契约——函数承诺做什么,而不是它当前如何做。这确保了即使实现演变,文档也能保持稳定。
黄金法则
当JSDoc添加了有助于开发者正确使用或维护代码的有意义信息时,才编写它。好的文档解释意图,警告陷阱,为决策提供上下文,并说明使用模式。它应该感觉像有一位经验丰富的同事在解释代码的重要部分,而不是阅读类型签名中已经可见内容的冗余转录。
有关常见模式和反模式的详细示例,请参见 references/patterns.md。