ECC 规则体系实战TypeScript/JavaScript 模式规范patterns.md深度解读与代码实现指南【免费下载链接】ECCThe agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.项目地址: https://gitcode.com/GitHub_Trending/ev/ECC本文以 ECCThe agent harness performance optimization system规则库中的 rules/typescript/patterns.md以及其西班牙语文档 docs/es/rules/typescript/patterns.md为核心系统解读 ECC 为 TypeScript/JavaScript 代码生成的 Agent 所沉淀的三类核心编码模式API 响应格式API Response Format、自定义 Hooks 模式Custom Hooks Pattern与仓储模式Repository Pattern。文章逐项还原每个模式的完整代码骨架并从 ECC 仓库中已有实现与配套规则如 console.log 检测 Hook反推其背后的工程动机与落地方法让读者在阅读与编写 TS/JS 代码时能直接套用这套可被 Agent 与人工评审一致执行的规范。一、这份规则文档在 ECC 中的定位与作用方式ECC 是一个面向 Claude Code、Codex、Opencode、Cursor 等编码 Agent 的性能优化系统通过 rules 目录为不同语言提供分门别类的规则文件确保 Agent 在自动生成、审查代码时遵循统一范式避免每次生成的代码风格漂移、边界处理缺失。本文档即rules/typescript/规则组中的patterns.md。规则文件开头的 front matter 明确声明了它的作用范围paths: - **/*.ts - **/*.tsx - **/*.js - **/*.jsx它意味着当 Agent 编辑或评审任意.ts/.tsx/.js/.jsx文件时本规则自动被加载并约束输出。同时文档头部写明了它与通用规则的层级关系本文件扩展 common/patterns.md 中与 TypeScript/JavaScript 相关的内容。也就是说通用规则先定义了做什么为什么要封装数据访问、为什么需要统一的响应信封语言级规则再给出怎么写具体的 TypeScript 泛型签名。两者叠加才是完整规范。同目录下还配有一套互为补充的规则文件构成完整的语言约束矩阵rules/typescript/coding-style.md类型/接口使用、不可变性、错误处理、any规避等编码风格rules/typescript/hooks.md编辑器/Agent Hook 侧的自动格式化与静态检查约定rules/typescript/security.md 与 rules/typescript/testing.md安全与测试侧规则。这种front matter 声明作用路径 文档互相引用 语言规则分层扩展的结构正是 ECC 让 Agent 可确定性遵循工程规范的关键机制。二、API 响应格式用统一信封约束所有接口2.1 规则原文中的信封结构patterns.md 给出的核心骨架如下interface ApiResponseT { success: boolean data?: T error?: string meta?: { total: number page: number limit: number } }这是一份对所有 API 返回值形态的强制约定。对照 common/patterns.md 中API Response Format一节的要求可以还原出每个字段的设计意图字段类型含义与取值约束successboolean成功/失败状态指示器所有响应都必须有dataT \| undefined成功时的数据负载失败时置空errorstring \| undefined失败时的错误消息成功时置空meta可选对象分页响应的元数据total总数、page页码、limit每页条数2.2 为什么需要这层信封客户端处理路径统一无论调用哪个端点消费方永远先看success再决定走data分支还是error分支不需要为每个接口记忆一套专属的失败返回结构。成功与失败互斥data在失败时缺省、error在成功时缺省杜绝既返回业务数据又返回错误串的歧义状态。分页元数据固化凡是列表接口分页信息不再散落在响应体的任意角落而是统一收进meta前端可直接透传给分页组件。2.3 落地增强让信封具备运行时收敛能力仅有接口声明还不够——类型会在编译期消失因此调用方如何安全地取出 data才是实战中的关键。可以用类型守卫把success收窄为可判别联合discriminated union让成功/失败分支在类型层面彼此独立// 升级为可判别联合success 作为 discriminant type ApiResultT | { success: true; data: T; meta?: { total: number; page: number; limit: number } } | { success: false; error: string } // 类型守卫一旦返回 trueTS 即把 result 收窄为成功分支 function isSuccessT(result: ApiResultT): result is ExtractApiResultT, { success: true } { return result.success } // 消费示例无需任何 as 断言 const result await apiFetchUser[](/users?page1limit20) if (isSuccess(result)) { // result.data 在此分支中已被确认存在 renderTable(result.data) } else { showToast(result.error) }通用错误处理规范见 rules/typescript/coding-style.md 中Error Handling一节——它要求async/await配合try-catch并对unknown错误先做安全收窄再使用与上述error字段的收窄逻辑是同一思路的延续。三、Custom Hooks 模式把防抖逻辑封装成可复用 React Hook3.1 规则原文中的 useDebounceReact 组件中大量出现输入框防抖、窗口尺寸节流、订阅清理等副作用逻辑。patterns.md 给出的约定样例是useDebounceexport function useDebounceT(value: T, delay: number): T { const [debouncedValue, setDebouncedValue] useStateT(value) useEffect(() { const handler setTimeout(() setDebouncedValue(value), delay) return () clearTimeout(handler) }, [value, delay]) return debouncedValue }3.2 逐行拆解其工程要点泛型T保留类型useDebounceT(value: T, delay: number): T让 Hook 对字符串、对象、数组等任意输入值通用且返回值与输入值类型强一致不会因防抖丢失类型信息。useState初始化即当前值首帧渲染直接返回传入的value保证页面不因防抖出现空白闪烁。useEffect内定时器 清理函数成对出现每次value或delay变化旧定时器先被clearTimeout清理再注册新定时器组件卸载时同样触发清理杜绝内存泄漏与卸载后 setState告警。依赖数组[value, delay]精确声明只要这两个输入之一变化就重建定时器是最小且充分的依赖集合。副作用函数必须返回清理函数——这是自定义 Hook 与useEffect配合时的铁律。3.3 典型使用场景搜索请求防抖function SearchBox() { const [keyword, setKeyword] useState() const debouncedKeyword useDebounce(keyword, 300) useEffect(() { if (!debouncedKeyword.trim()) return fetch(/api/search?q${encodeURIComponent(debouncedKeyword)}) .then(res res.json()) .then(data setResults(data)) }, [debouncedKeyword]) return input value{keyword} onChange{e setKeyword(e.target.value)} / }这样用户每敲击一次键盘只触发setKeyword而真正的搜索请求被延迟到连续输入停顿 300ms 后才发起。规则文档本身只保留最小骨架实际项目还可以在其上继续组合出useDebouncedCallback、useThrottle、usePrevious等变体——但骨架必须遵循命名以use开头、内部使用 React Hooks、清理副作用这三大原则否则无法通过 rules/typescript/testing.md 与 rules/typescript/hooks.md 的约束。四、Repository 模式为数据访问套上一层抽象接口4.1 规则原文中的仓储契约interface RepositoryT { findAll(filters?: Filters): PromiseT[] findById(id: string): PromiseT | null create(data: CreateDto): PromiseT update(id: string, data: UpdateDto): PromiseT delete(id: string): Promisevoid }注意这里的方法名与 common/patterns.md 完全对应findAll、findById、create、update、delete。语言规则负责把通用规则中的这五个标准操作翻译成带类型签名的异步方法全部返回Promise符合现代 Node/前端对异步 IO 的假设findById用T | null显式表达可能查无此人而不是抛异常或返回undefined。4.2 分层语义RepositoryT只负责数据访问的形态约定不包含任何存储实现细节。业务代码面向接口编程底层实现可以自由切换为数据库、HTTP API 或纯内存存储// 内存实现适合测试与原型 class InMemoryUserRepository implements RepositoryUser { private store new Mapstring, User() async findAll(filters?: Filters): PromiseUser[] { return [...this.store.values()].filter(matchFilters(filters)) } async findById(id: string): PromiseUser | null { return this.store.get(id) ?? null } async create(data: CreateUserDto): PromiseUser { const user { ...data, id: crypto.randomUUID() } this.store.set(user.id, user) return user } async update(id: string, data: UpdateUserDto): PromiseUser { const existing this.store.get(id) if (!existing) throw new Error(User ${id} not found) const updated { ...existing, ...data } this.store.set(id, updated) return updated } async delete(id: string): Promisevoid { this.store.delete(id) } }4.3 使用 Repository 模式带来的收益可替换性从 SQL 数据库切换到 REST API 或缓存层时只需替换实现类Service 层零改动——这正是 common/patterns.md 中轻松切换数据源的落地方式。可测试性业务测试可以注入内存假实现或 mock无需启动真实数据库配合 rules/typescript/testing.md 中关于隔离 IO 的测试约定单测速度与稳定性显著提升。类型即文档CreateDto/UpdateDto/Filters分别约束创建所需字段、更新允许字段、筛选条件把仓储对外接口的输入边界收敛到类型层面接口误用会在编译期就被拦截。4.4 在 ECC 中的配套约束仓储模式并非想怎么实现就怎么实现。ECC 的 TypeScript 规则组对其施加了更多约束方法与入参须显式标注类型、避免内部any见 rules/typescript/coding-style.md 的 Avoidany 小节外部不可信输入应使用unknown收窄对象更新使用展开运算符保持不可变coding-style.md 的 Immutability 小节上面内存实现中的{ ...existing, ...data }即此规范生产代码不得出现裸console.log应改用正式日志库。五、源码级佐证ECC 如何自己落实模式即约束ECC 不仅把这三类模式写成规则更在自己仓库中用工具链把它们变成可自动执行的检查。以下是可在仓库中直接核验的实现证据。5.1 console.log 自动审计 Hookcoding-style.md 规定 Noconsole.logstatements in production codepatterns.md 所属的规则组rules/typescript/hooks.md则要求通过 Hook 自动提醒。仓库 scripts/hooks/check-console-log.js 正是该检查的执行器它通过getGitModifiedFiles([\\.tsx?$, \\.jsx?$])只扫描被修改的 TS/JS 文件通过EXCLUDED_PATTERNS白名单跳过.test.*、.spec.*、.config.*、scripts/、__tests__/、__mocks__/等允许打印日志的路径一旦发现命中console.log即输出WARNING: console.log found in file并提示在提交前移除。这个 Hook 是规则文档 → 自动化检查闭环的直接例证文档定义模式脚本保障执行两者一起构成 Agent 与人工评审共同遵守的规范底座。5.2 规则文件间的交叉引用patterns.md 声明扩展自 common/patterns.md因此仓储五方法与响应信封语义的为什么应查阅 common/patterns.md模式实现时的怎么写更安全应查阅同组 coding-style.md类型标注、不可变性、unknown收窄、Zod 输入校验代码落地后的自动防线应查阅 hooks.mdPrettier 自动格式化、tsc类型检查、console.log 告警与 testing.md。5.3 查阅与扩展方式英文原版规则rules/typescript/patterns.md本仓库西班牙语文档docs/es/rules/typescript/patterns.md通用模式基准docs/es/rules/common/patterns.md其余 TS 语言规则同一paths作用域coding-style.md、hooks.md、security.md、testing.md自动化执行示例scripts/hooks/check-console-log.js。六、三模式协同使用一套可落地的 TS/JS 工程范式小结模式解决的核心问题最小骨架仓库内配套规则API 响应格式所有接口返回结构不统一客户端处理路径发散ApiResponseTsuccess/data/error/metacommon 通用信封约定 coding-style 的 unknown 收窄Custom Hooks副作用与重复交互逻辑散落组件内难以测试复用useDebounceTstate effect 清理函数testing.md 的 Hook 测试与 hooks.md 的自动检查Repository业务逻辑与存储细节耦合数据源难以替换RepositoryT五方法异步契约common 仓储原则 coding-style 的类型/不可变约束三者共同回答了一个工程问题面对一个会持续演进、且由 Agent 大规模参与生成/评审的 TS/JS 代码库如何让返回结构、副作用逻辑、数据访问这三类最高频代码保持形态一致、边界清晰、可测试、可替换。使用这套规则时建议按以下顺序落地先让所有 API 层返回统一信封配合类型守卫消费把所有跨组件复用的副作用收敛为自定义 Hook从useDebounce这类最小原语起步将持久化/远程数据访问封装进仓储接口业务层只依赖抽象最后开启同目录 hooks.md 约定的 Prettier tsc console.log 审计让机器守住这些模式不被日常提交侵蚀。这样文档里的模式才能变成代码库里的现实而这正是 ECC 作为 Agent 工程规范系统的核心设计意图。【免费下载链接】ECCThe agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.项目地址: https://gitcode.com/GitHub_Trending/ev/ECC创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考