mcpField
T
typescript-conventions

typescript-conventions

github.com/perdolique开发043 次安装2 天前更新
代码仓库

关于 typescript-conventions

为 TypeScript 仓库中的开发者提供编码与审查规范,涵盖运行时校验、表达式组织、包装函数、展开操作、类型结构及非显而易见决策的说明。

主要功能

  1. 01使用 Valibot 进行运行时校验
  2. 02提取非简单计算
  3. 03避免纯转发包装函数
  4. 04确保每个展开操作有明确目的
  5. 05保持命名对象类型扁平
  6. 06说明非显而易见的决策

适用场景

  1. 01编写 TypeScript 时遵循规范
  2. 02审查 TypeScript 改动的可维护性

安装

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

$npx skills add https://github.com/perdolique/workflow --skill typescript-conventions

安装后在 Claude Code 中输入/typescript-conventions确认已加载。

附带文件evals/evals.json

详细介绍

TypeScript 编码约定

  • 优先遵循当前文件适用的仓库文档、AGENTS.md、lint 规则和配置。将本指南用于 TypeScript(包括嵌入的 TypeScript),并在需要时结合可用的框架、测试或库技能。
  • 使用 Valibot 定义运行时验证 schema,遵循项目的 schema 组织方式,并在适用时复用现有契约。

避免 return undefined

不要使用 return undefined。函数不返回值而退出时,使用不带值的 return。

提取非平凡的中间计算结果

  • 将非平凡计算嵌入参数、属性值、数组元素、条件、循环输入、展开源、返回值或更大的表达式之前,先将其赋给一个命名的 const 或 let。
  • 在普通嵌套调用、await 的值、构造函数、链式转换、模板拼接的值、三元表达式和包含多个运算符的表达式被其他计算使用之前,为它们赋予有意义的中间变量名。
  • 例外:可以将一目了然的基础表达式直接内联,包括属性或元素访问、可选链、??、一元检查、简单比较和单步算术。不要仅为满足此规则而拆分它们。若初始化表达式本身已经为结果赋予了有意义的名称,则其中可以包含清晰的计算。
  • 按执行顺序安排存在依赖关系的语句:先解析输入,再转换输入,然后使用结果。
  • 对声明式库 API(嵌入式 DSL)中的嵌套或链式调用予以保留,只要其结构表达的是声明,例如 schema、查询或规则集。遵循该 API 既有的组合风格。将作为输入的普通数据准备工作提取出来;例如,在 eq(users.id, id) 中使用 parseId(rawId) 之前,先为其结果命名。数据转换链应遵循常规的提取规则。
  • 保持行为和算法复杂度不变;不要仅为格式调整而添加中间集合或额外遍历。

避免无意义的直通包装函数

  • 不要创建只负责调用另一个函数,并立即返回其结果或对其结果执行 await、却不增加任何行为的函数。如果包装函数没有命名一个真正的概念,也不负责验证、分支、重试、映射、埋点或错误处理等逻辑,请在调用处直接调用底层函数,或重命名底层函数。
  • 只有在包装函数能建立更清晰的领域边界,或添加调用方不应重复实现的行为时,才使用包装函数。

尽可能让包装契约归属于源 API

  • 包装有类型的 API 时,应优先复用源 API 的类型和类型推导。只有当包装函数负责更窄的契约,或类型检查证明类型推导不足时,才添加本地命名类型。
  • 如果包装函数改变了返回值或错误的形态、生命周期、验证、映射或副作用,请为其拥有的契约命名并编写测试。

每次展开都必须有具体理由

  • 每个对象或数组展开都必须在创建位置服务于具体目的,例如不可变地更改选定字段、合并集合,或建立必要的所有权边界。如果不会修改原值,且共享它是安全的,就直接复用,而不是创建浅拷贝。不要为了防御性处理或让代码看起来不可变而展开。
  • 创建视图模型、API payload 或其他经过有意塑形的对象时,应明确列出其属性。不要使用宽泛的源对象展开,以免隐藏最终契约或复制无关字段。展开是浅拷贝;若所需隔离更深,则不要使用展开。
  • 编写和审查代码时,应能说明每次展开的用途。只有当周边操作无法清楚体现用途时,才添加简短的代码注释。生产代码、测试和 fixture 都遵循同一标准;有针对性的 fixture 覆盖是合理用途,不必要的复制则不是。

优先采用扁平的接口结构

  • 将 interface 声明和具名对象 type 别名限制为一层具名属性。若某个属性需要对象形状,请将该形状提取为单独的具名接口,并在父类型中引用它。
  • 此规则适用于直接对象属性、对象数组,以及可空或联合形式,例如 brand: { ...}、items: { ... }[] 和 brand: { ... } | null。
  • 此规则仅适用于类型声明,不适用于运行时对象字面量、验证器模式、框架配置对象或库 DSL 值,因为这些对象形状属于可执行配置,而非可复用的类型约定。

说明不明显的决策

  • 如果代码无法清楚体现某项用途、外部约束或变通方案,请添加简短注释。对于共享工具,请说明它所负责的约定,尤其是在相邻层容易让人混淆其作用时。
  • 简化代码时保留原因。对于显而易见的机制,使用清晰的名称和结构,而不是逐行叙述或加入无关的实现细节。

评论

支持 Markdown