Community写作与编辑github.com

spnngl/agent-skills

TypeScript 编码工作流与惯用法,涵盖 React、Next.js、Recharts 和 Zod。适用于编写、审查或重构 TypeScript、TSX 或带 JSDoc 类型标注的 JavaScript,以及编辑 tsconfig.json、package.json、workspace 或 Biome、oxlint、oxfmt 配置。

agent-skills 是什么?

该技能提供了一套全面的 TypeScript 编码工作流和规则,专为 AI 代理(如 Claude Code、Cursor、Codex)设计。它强调在编写代码前先了解项目结构(包括 package.json、tsconfig.json、lint/format 配置及 CI 命令),并通过严格的类型优先方法确保代码质量。技能规则涵盖类型安全(禁止 any、非空断言和类型断言,推荐鉴别联合、品牌类型和解析而非验证)、错误处理(返回结果联合或抛出带有 cause 的错误)以及异步编程(每个 Promise 都必须被处理)。此外,技能还维护了一份现代 TypeScript 惯用法对照表(如使用 satisfies 替代类型断言、using 替代 try/finally 清理),并引用了一系列参考文档(涵盖类型、错误、模块、Zod、React、Next.js、Recharts、测试等),以指导具体的实现细节。该技能要求代理在完成每个步骤后都要进行自检,并在审查他人代码时遵循相同的流程。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/spnngl/agent-skills/tree/HEAD/skills/typescript/ts-coding

Installed? Explore more 写作与编辑 skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

TypeScript 编码

工作流

  1. 了解项目。 在编写代码之前,先阅读项目的权威来源:package.json(type、engines、packageManager、exports、scripts、已安装的主要版本)、lockfile、每个 tsconfig*.json 及其 extends 链、根工作区、框架、lint 和格式配置(pnpm-workspace.yaml、turbo.json、next.config.ts、biome.json、.oxlintrc.json),以及 CI 中的规范检查命令。运行 tsc --showConfig 来解析 extends 链;它会省略那些保持默认值的选项,因此请从 references/modules.md(TypeScript 6 和 7 已更改默认值)中读取这些选项。阅读你正在修改的模块及其相邻模块;重用它们的辅助函数、错误类型、模式和模式。 完成条件: 你能够说出包管理器、TypeScript 主版本号、module 和 moduleResolution、strict 之外的严格标志(noUncheckedIndexedAccess、exactOptionalPropertyTypes、erasableSyntaxOnly)、lint 和格式工具链,以及项目的检查命令。

  2. 设计类型。 先设计数据,再设计控制流,遵循 类型 的规则。来自进程外部的输入:阅读 references/zod.md。修改包的公开 API:阅读 references/api.md。 完成条件: 变更所依赖的每个不变量都用类型编码,并且每个跨越信任边界的值在使用前都经过模式解析。

  3. 紧凑循环实现。 以小步骤工作,并在每一步之后运行 tsc --noEmit(对于有项目引用的项目,使用 tsc -b)。阅读完整的诊断信息;其代码(如 TS2742)是搜索 references/modules.md 和 references/types.md 中表格的关键。对于依赖项的 API,在 node_modules/<pkg>/ 下阅读已安装版本的 .d.ts 文件。Bug 修复:先编写回归测试并观察它失败。 完成条件: 变更在类型检查时没有新的诊断信息,并且任何回归测试在修复前变红,修复后变绿。

  4. 验证。 通过包管理器(pnpm exec、npx、bunx)运行步骤 1 中的项目命令;否则,针对项目使用的工具链,运行以下命令:

    tsc --noEmit                                           # 当 tsconfig.json 仅列出引用时,使用 tsc -b
    biome ci                                               # Biome
    oxfmt --check && oxlint --type-aware --deny-warnings   # oxlint + oxfmt
    vitest run --typecheck                                 # 或项目的测试运行器
    
    • 根目录下的 tsconfig.json 如果包含 "files": [] 和 references,会使 tsc --noEmit 什么都不检查;应使用 tsc -b。在没有根 tsconfig 的工作区中,通过任务运行器(turbo run check-types test)在每个包中运行检查。
    • 在每个 linter 的循环中都要保留 tsc:Biome 的类型推断和 oxlint 的类型感知规则是对它的补充,绝不能替代它。
    • 格式化失败:应使用格式化器(biome check --write、oxfmt)应用格式,而不是手动编辑。
    • 在根本原因处修复诊断信息。当必须抑制时,将其范围限定在一行内并给出理由:// biome-ignore lint/<group>/<rule>: reason、// oxlint-disable-next-line <rule> -- reason、// @ts-expect-error reason。
    • 如果修改了 lint 或格式配置:对照 references/lints.md 进行检查,然后对整个仓库运行 linter 和格式化器,而不仅仅是修改过的文件。
    • 如果修改了已发布包的公共 API:运行 references/api.md。 完成条件: 每个命令都返回 0,你修改的行没有产生任何警告,并且每个新的抑制都带有理由。
  5. 自审差异。 重新阅读完整的 git diff(对于新文件,使用 git add -A && git diff --cached),而不是凭记忆,并对照 规则 以及 diff 涉及到的每个参考文件的规则进行检查。 完成条件: 每个块都是任务必需的,console.log、debugger、.only 和注释掉的代码已被删除,文档注释与行为一致,并且所有适用的规则都适用于每个块。

审查 他人的代码:执行步骤 1,在可能的情况下执行步骤 4 的命令,然后将步骤 5 应用于他们的 diff。将每个发现报告为 path:line、规则和修复方法。

规则

类型

  • 用证据缩小类型范围:typeof、instanceof、in、鉴别检查、类型谓词或模式解析。禁止使用 any、非空断言 ! 和 as T(测试中也禁止);保留 as const 和 satisfies。当库的类型错误时,使用模块扩充在源头修复它们 (references/types.md)。
  • 使非法状态不可表示:使用带字面量 kind 字段的鉴别联合,而不是 boolean 标志加可选字段。通过模式(z.string().brand<"UserId">())或类型谓词对 ID、单位和已验证的值进行品牌化,绝不要使用 as。
  • 解析,而非验证:JSON.parse、Response.json()、环境变量、存储、URL 参数和 postMessage 数据在边界处被 Zod 模式解析前都是 unknown;将解析后的类型向内传递。
  • 对自己拥有的联合类型使用穷举 switch:以 default: x satisfies never; throw new Error(...) 结束,或者使用 Record<Union, V> 查找表,当添加新成员时会导致编译失败。
  • 在 noUncheckedIndexedAccess 下,索引访问返回 T | undefined:处理 undefined(使用守卫、?? fallback、for...of),而不是断言它不存在。
  • 导出的函数声明其返回类型;局部变量保持推断。
  • 对象形状使用 interface,使用 extends 而非 & 交叉类型;联合、映射和条件类型使用 type。
  • 对于函数不进行修改的输入,接受 readonly T[] 和 Readonly<T>。
  • 优先使用字符串字面量联合或 as const 对象,而不是 enum 和带有运行时代码的命名空间(两者在 erasableSyntaxOnly 下都被禁止)。

错误与异步

  • 调用者必须处理的预期失败返回一个结果联合;错误和不可恢复的状态抛出一个带有 { cause } 的 Error 子类。详情: references/errors.md。
  • 每个 Promise 都必须被 await、返回或传递给一个观察其拒绝的处理程序。

当前惯用法

训练数据早于 TypeScript 6 和 7:TypeScript 7 是基于 Go 的编译器,strict 默认开启,types 默认为 [],并且 baseUrl、outFile、target: "ES5" 和 moduleResolution: "node10" 已被移除 (references/modules.md)。在已安装版本允许的情况下,优先使用当前形式,包括通过 lib 级别 使用标准库 API。当参考文件与已安装包的 .d.ts 或 CHANGELOG 不一致时,以已安装版本为准。

优先使用而不是自版本
const config = { ... } satisfies Configconst config: Config(会拓宽)、as Config4.9
function f<const T>(x: T)在每个调用点使用 as const5.0
使用 verbatimModuleSyntax 的 import type { T }importsNotUsedAsValues(已移除)5.0
使用 [Symbol.dispose] 的 using / await usingtry / finally 清理5.2, lib esnext
import data from "./d.json" with { type: "json" }assert { type: "json" }(自 6.0 起报错)5.3
NoInfer<T>T & {} 推理阻塞器5.4
推断谓词:xs.filter((x) => x !== undefined)手写 (x): x is T => 守卫5.5

文档与注释

  • 导出的项需要 /** */ 文档,说明合约:@throws 用于抛出的错误,@deprecated 指明替代项,当签名不能明显说明用法时提供 @example。

依赖

  • 重用 package.json 中已有的内容,并在平台满足需求时优先使用平台:fetch、structuredClone、crypto.randomUUID、AbortSignal.timeout、node: 前缀的内置模块。
  • 使用项目的包管理器添加依赖,并将 @types/* 固定到运行时包的主版本号(@types/node:固定到 engines 中最低的 Node 版本)。

参考

加载与你当前所在分支匹配的那个:

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

相关技能