关于 typescript-best-practices
面向 TypeScript 开发者的技能,强调用类型让无效状态难以表达,并涵盖建模、边界验证、测试和遥测实践。
主要功能
- 01判别联合与品牌类型
- 02通过构造表达有效值
- 03在数据边界验证外部输入
- 04优先使用 Schema 和派生类型
- 05穷尽匹配与安全收窄
- 06真实测试与结构化遥测
适用场景
- 01建模变体,避免可选字段堆叠
- 02防止语义 ID 意外混用
- 03将不可信输入解析为领域类型
- 04检查 TypeScript 代码中的不安全断言
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mdsmithaustin/ pstack --skill typescript-best-practices安装后在 Claude Code 中输入/typescript-best-practices确认已加载。
附带文件agents/openai.yamlreferences/patterns.md
详细介绍
TypeScript 最佳实践
首先调用 Skill 工具 principle-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>(无论如何书写)都应止步于解析处。内部信任类型。调用 Skill 工具 principle-boundary-discipline。 |
| 从 Schema 推导类型 | 声明新接口之前,优先考虑 Pick/Omit/Parameters/ReturnType/Awaited/typeof。 |
| 对象参数 | 传递对象而非位置参数,让参数顺序一目了然。高频路径(逐帧渲染、分词器、解析器)除外。 |
| 真实测试 | 能实际运行的就不要模拟。优先使用框架真实的测试原语,并检查泄漏与可释放性;在运行中的构建版本里验证 UI。只模拟无法在本地运行的部分。 |
| 结构化遥测 | 优先使用上下文充分的结构化日志诊断信息,以便通过 id 调试。发布代码中不要使用 console.log。 |
示例:references/patterns.md。
评论
支持 Markdown