mcpField
N
no-type-in-docs

no-type-in-docs

github.com/marius-townhouse开发644 次安装38 周前更新
代码仓库

关于 no-type-in-docs

这项 TypeScript 技能建议将类型信息保留在类型标注中,不要在注释里重复。它帮助开发者让文档聚焦于代码的目的与意图。

主要功能

  1. 01避免在注释中重复类型
  2. 02用注释说明意图
  3. 03用 JSDoc 说明参数含义
  4. 04变量名避免包含类型信息
  5. 05用 readonly 表达不可变约束

适用场景

  1. 01检查函数注释与 JSDoc
  2. 02编写 TypeScript API 文档
  3. 03改进变量命名
  4. 04避免重复类型标注并阐明代码

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/marius-townhouse/effective-typescript-skills --skill no-type-in-docs

安装后在 Claude Code 中输入/no-type-in-docs确认已加载。

详细介绍

不要在文档中重复类型信息

概述

类型注解就是文档。不要在注释中重复类型信息。

描述类型的注释会与代码脱节。TypeScript 的类型系统设计得简洁易读——请将其作为类型文档的主要来源。

何时使用此技能

  • 为函数编写 JSDoc 或注释
  • 记录参数类型
  • 为变量命名
  • 描述返回值

铁律

Never put type information in comments.
Let the type annotations speak for themselves.

请记住:

  • 注释会与代码脱节;类型会经过检查
  • 类型注解的设计目标就是易读
  • 注释应该解释原因,而不是类型是什么
  • 变量名不应包含类型信息

检测:注释中的类型信息

/**
 * Returns a string with the foreground color.
 * Takes zero or one arguments. With no arguments, returns the
 * standard foreground color. With one argument, returns the foreground color
 * for a particular page.
 */
function getForegroundColor(page?: string) {
  return page === 'login' ? {r: 127, g: 127, b: 127} : {r: 0, g: 0, b: 0};
}

问题:

  • 注释说“返回一个字符串”,但函数返回的是一个对象
  • 注释描述参数数量(签名中一目了然)
  • 注释比实现本身还长!

更好的文档

/** Get the foreground color for the application or a specific page. */
function getForegroundColor(page?: string): Color {
  // ...
}

类型签名会告诉你:

  • 参数是可选字符串
  • 返回类型是 Color
  • 无需在注释中重复这些信息

不要记录不可变性

// Bad: comment lies (sort() mutates in place)
/** Sort the strings by numeric value. Does not modify nums. */
function sortNumerically(nums: string[]): string[] {
  return nums.sort((a, b) => Number(a) - Number(b));
}

// Good: type enforces non-mutation
/** Sort the strings by numeric value. */
function sortNumerically(nums: readonly string[]): string[] {
  return nums.toSorted((a, b) => Number(a) - Number(b));
}

TypeScript 会强制执行 readonly 修饰符,而注释不会。

变量名

变量名中不要包含类型信息:

// Bad: redundant type in name
const ageNum = 30;
const nameString = 'Alice';
const usersArray = [];

// Good: descriptive names, types inferred
const age = 30;
const name = 'Alice';
const users = [];
例外:单位

当单位无法从类型中看出时,请将其包含在名称中:

// Good: units aren't captured by type
const timeMs = 1000;
const temperatureC = 20;
const distanceKm = 5.5;

// Better: use branded types (Item 64)
type Milliseconds = number & { _brand: 'ms' };
const time: Milliseconds = 1000 as Milliseconds;

JSDoc 最佳实践

使用 @param 记录参数信息,而非类型信息:

/**
 * Formats a user's display name.
 * @param user - The user to format
 * @param options - Formatting options
 * @returns The formatted display name
 */
function formatDisplayName(
  user: User,
  options?: FormatOptions
): string {
  // ...
}

不要重复类型信息:

// Bad: duplicates types
/**
 * @param user {User} - The user object
 * @param options {FormatOptions | undefined} - Optional formatting options
 * @returns {string} The formatted name
 */

注释应该包含的内容

  • 用途和意图
  • 业务逻辑说明
  • 算法描述
  • 不明显的行为
  • 相关文档链接
/**
 * Calculates compound interest using the standard formula.
 * See: https://en.wikipedia.org/wiki/Compound_interest
 */
function compoundInterest(
  principal: number,
  rate: number,
  periods: number
): number {
  // P(1 + r)^n
  return principal * Math.pow(1 + rate, periods);
}

抵御压力守则

1. “注释能让代码更易读”

压力:“我想记录类型,让代码更清晰”

**回应:**类型本身就是文档。它们会经过检查,始终准确。

**行动:**从注释中移除类型信息。如果类型名称不清晰,请改进名称。

2. “我需要记录复杂类型”

压力:“这个类型很复杂,我需要解释一下”

**回应:**在类型定义本身使用 TSDoc。

**行动:**为类型添加文档,而不是为类型的使用位置添加文档。

危险信号——停下来重新考虑

  • 注释中提到“返回一个字符串”或类似内容
  • 注释中提到参数数量
  • 声称“不会修改”(改用 readonly)
  • numUsers 或 strName 这类变量名

常见自我辩解(都不成立)

借口事实
“这样更易读”类型本来就设计得易读
“不是所有人都懂 TypeScript”他们可以将鼠标悬停在类型上或点击查看
“文档总是有益的”过时的文档有害

快速参考

// DON'T: Type info in comments
/** Returns string, takes number */ 
function f(n: number): string { ... }

// DON'T: Claim non-mutation in comments
/** Does not modify array */
function sort(arr: number[]): number[] { ... }

// DON'T: Types in variable names
const ageNum = 30;

// DO: Describe purpose, not types
/** Get display name for UI header */
function getName(user: User): string { ... }

// DO: Use readonly for non-mutation
function sort(arr: readonly number[]): number[] { ... }

// DO: Units in names when helpful
const timeMs = 1000;

总结

类型注解就是文档。

TypeScript 的类型系统表现力强且始终准确。有关类型的注释会与代码脱节,误导读者。请用注释解释用途、意图和业务逻辑,而不是类型。

参考资料

改编自 Dan Vanderkam 的《Effective TypeScript》第 31 条:不要在文档中重复类型信息。

评论

支持 Markdown