关于 typescript-best-practices
typescript-best-practices 是一项指导 TypeScript 类型系统实践的技能,着重于建模有效状态、在边界验证数据,以及针对真实行为编写测试。
主要功能
- 01用可辨识联合建模变体
- 02为已验证的原始值使用品牌类型
- 03优先使用 unknown 而非 any
- 04从运行时 schema 派生类型
- 05检查 switch 分支的穷尽性
适用场景
- 01设计可避免无效状态的领域类型
- 02在输入边界验证外部数据
- 03审查 TypeScript 类型断言与类型守卫
- 04使用真实测试框架原语编写测试
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ cursor/ plugins --skill typescript-best-practices安装后在 Claude Code 中输入/typescript-best-practices确认已加载。
附带文件references/patterns.md
详细介绍
TypeScript 最佳实践
请先应用 type-system-discipline 原则技能。
| 规则 | 概述 |
|---|---|
| 可辨识联合 | 使用 kind 字面量判别字段对不同变体建模,确保无法表示不可能的状态。不要使用可选字段集合。 |
| 品牌类型 | 使用 & { readonly __brand: "X" } 为基本类型添加品牌,避免类型混淆。在边界处验证一次。品牌必须来自验证型类型守卫(input is AgentId),绝不能来自 as。 |
| 构造式建模 | 构建类型结构,使非法值无法被构造。非空类型使用 [T, ...T[]],偶数长度使用 [T, T][],范围使用 start 加 duration。这不是运行时守卫,也不是对精化类型的空想。 |
| 最简单的全函数类型 | 只要对 T[] 的每项操作都保持全函数,就继续使用 T[]。只有在宽松类型会迫使你使用 !、类型断言或“理论上不可能发生”的抛错时,才加强为 NonEmpty<T>。 |
用 unknown 而非 any | 外部数据的类型是 unknown。 |
| 先用 Schema,再写守卫 | 手写逐属性类型守卫之前,先使用仓库的运行时 Schema 库,并从 Schema 推导类型,例如 z.infer。 |
不使用 as 类型断言 | 每个 as 都像一场等待发生的运行时崩溃。只有在验证之后才能使用类型断言。 |
| 窄化层级 | 判别字段 switch > in 运算符 > typeof/instanceof > 用户定义的类型守卫 > as。 |
| 类型守卫 | 必须验证所声称的内容。说谎的守卫比 as 更糟,因为错误会藏在一个看似安全的名称背后。命名为 isX 或 hasX。 |
| 穷尽性检查 | 在 default 分支中内联 const _exhaustive: never = x;,这样添加新变体时编译器会报错。 |
用 satisfies 而非 as | 验证值而不扩大字面量类型。 |
| 边界验证 | 在数据进入系统时解析,并转换为具名领域类型。无论如何书写,Record<string, unknown> 都应止步于该解析处。在内部信任类型。请参阅 boundary-discipline 原则技能。 |
| 从 Schema 推导类型 | 声明新接口之前,先考虑使用 Pick/Omit/Parameters/ReturnType/Awaited/typeof。 |
| 对象参数 | 传递对象而非位置参数,让参数顺序一目了然。在热点路径(逐帧渲染、分词器、解析器)中除外。 |
| 真实测试 | 能实际运行的就不要模拟。优先使用框架真实的测试基元,并检查资源泄漏和可释放对象;在运行中的构建中验证 UI。只模拟无法在本地运行的内容。 |
| 结构化遥测 | 优先使用包含足够上下文、便于根据 ID 调试的结构化日志诊断。已发布代码中不使用 console.log。 |
示例:references/patterns.md。
评论
支持 Markdown