ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

ECC TypeScript/JavaScript 编码规范实战指南:从类型安全到自动化钩子的完整落地

ECC TypeScript/JavaScript 编码规范实战指南:从类型安全到自动化钩子的完整落地 ECC TypeScript/JavaScript 编码规范实战指南从类型安全到自动化钩子的完整落地【免费下载链接】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本篇技术指南以 ECC 仓库中的 TypeScript/JavaScript 编码规范 为核心骨架结合仓库内实际的 ESLint 配置、Hook 脚本与通用规则系统讲解在 Claude Code、Codex、OpenCode、Cursor 等 Agent 工作流中编写高质量 TypeScript/JavaScript 代码的规范体系。读完本文你将掌握公共 API 类型标注、interface/type取舍、any规避、不可变更新、错误处理与 Zod 校验的完整模式并了解如何通过 ECC 的 Hook 机制让console.log与格式检查实现自动化拦截。ECC 将编码规范rules作为 Agent 运行时可执行的行为准则每个规范文件通过 YAML front-matter 声明其适用的文件路径范围coding-style.md 声明为**/*.ts、**/*.tsx、**/*.js、**/*.jsxAgent 在编辑这些文件时自动加载对应规则。日语版本 docs/ja-JP/rules/typescript/coding-style.md 与英文版内容一致是同一规范体系的多语言分发。一、规范体系定位语言规则是通用准则的延伸TypeScript/JavaScript 编码规范并非孤立存在它显式声明为 common/coding-style.md 的扩展继承通用层的核心工程原则KISS优先选择最简单且真正可用的方案避免过早优化以清晰优先于炫技DRY将重复逻辑抽取为共享函数或工具避免复制粘贴导致实现漂移且只在重复真实存在时才引入抽象YAGNI不为尚未出现的需求预先构建特性或抽象先保持简单在真实压力出现时再重构不可变性CRITICAL永远创建新对象而非修改现有对象防止隐藏副作用、简化调试并支持安全并发。通用层还给出了文件组织的硬性约束多小文件优于少大文件源文件典型行数为 200-400 行800 行是软性可维护上限测试、生成与 vendor 文件可豁免按功能/领域组织而非按类型组织。命名上变量与函数用camelCase布尔值优先is/has/should/can前缀接口/类型/组件用PascalCase常量用UPPER_SNAKE_CASE自定义 Hook 用use前缀的camelCase。二、类型与接口让公共 API 显式、可读、可复用规范的第一要务是用类型让公共 API、共享模型与组件 props 显式、可读、可复用具体包含三条执行准则导出的函数、共享工具、公共类方法必须添加参数类型与返回值类型显而易见的局部变量类型交给 TypeScript 推断重复出现的行内对象结构应抽取为命名类型或接口。规范给出的正反例非常直观// 错误导出函数没有显式类型 export function formatUser(user) { return ${user.firstName} ${user.lastName} } // 正确公共 API 显式类型 interface User { firstName: string lastName: string } export function formatUser(user: User): string { return ${user.firstName} ${user.lastName} }这条规则背后是导出即契约的思想公共 API 的类型一旦缺失调用方与实现方就失去了共同约束重构时类型错误无法被编译器捕获。而局部变量类型标注属于噪音——TypeScript 的上下文推断contextual typing已经足够精确。interface 与 type alias 的取舍规范给出明确的二分法场景使用可能被扩展或实现的对象结构interface联合类型、交叉类型、元组、映射类型、工具类型type需要互操作性的枚举场景enum否则避免interface User { id: string email: string } type UserRole admin | member type UserWithRole User { role: UserRole }关键偏好是只要不因互操作性必须使用enum就用字符串字面量联合类型替代enum。理由在于enum生成运行时对象、破坏结构类型structurally typed的兼容性而字面量联合类型是纯类型层面的约束编译后被完全擦除且天然支持穷尽性检查。规避 anyunknown 强制安全收窄规范禁止在应用代码中使用any因为any会同时关闭编译器的类型检查与代码补全// 错误any 移除了类型安全 function getErrorMessage(error: any) { return error.message } // 正确unknown 强制安全收窄 function getErrorMessage(error: unknown): string { if (error instanceof Error) { return error.message } return Unexpected error }unknown是类型安全版本的 any对它的任何访问都必须先经过类型守卫type guard收窄。规范还指出当值的类型取决于调用方时应使用泛型而非any——这保证了类型信息在调用链中完整传递。React Props命名类型 显式回调类型组件 props 必须用命名的interface或type定义回调 props 显式标注函数签名且除非有明确理由不使用React.FCinterface User { id: string email: string } interface UserCardProps { user: User onSelect: (id: string) void } function UserCard({ user, onSelect }: UserCardProps) { return button onClick{() onSelect(user.id)}{user.email}/button }放弃React.FC的原因在社区已有共识它隐式携带children类型、不支持泛型组件、与默认参数的推断行为存在差异普通函数组件配合显式 props 接口更符合显式优于隐式的原则。JavaScript 文件JSDoc 作为类型声明对.js/.jsx文件当类型能显著提升可读性且暂时无法迁移到 TypeScript 时使用 JSDoc 标注并保持 JSDoc 与运行时行为一致/** * param {{ firstName: string, lastName: string }} user * returns {string} */ export function formatUser(user) { return ${user.firstName} ${user.lastName} }配合// ts-check或checkJs编译选项JSDoc 注释会参与真实类型检查是渐进式迁移路径上的低成本方案。三、不可变性用展开运算符替代原地修改规范将不可变性提升到与通用层相同的 CRITICAL 高度核心模式是展开运算符spread operatorinterface User { id: string name: string } // 错误原地修改 function updateUser(user: User, name: string): User { user.name name // 变异 return user } // 正确不可变更新 function updateUser(user: ReadonlyUser, name: string): User { return { ...user, name } }注意正确版本还有一处细节参数类型标注为ReadonlyUser从类型层面禁止了函数体内部的意外赋值返回全新对象而非原地修改避免调用方持有的旧引用被静默改变。在 React/Redux 生态中这一模式直接对应不可变状态更新的正确姿势。四、错误处理async/await unknown 收窄的组合拳规范推荐async/await搭配try-catch并在 catch 中安全收窄 unknown 错误interface User { id: string email: string } declare function riskyOperation(userId: string): PromiseUser function getErrorMessage(error: unknown): string { if (error instanceof Error) { return error.message } return Unexpected error } const logger { error: (message: string, error: unknown) { // 替换为你的生产日志库例如 pino 或 winston } } async function loadUser(userId: string): PromiseUser { try { const result await riskyOperation(userId) return result } catch (error: unknown) { logger.error(Operation failed, error) throw new Error(getErrorMessage(error)) } }这里体现了三层意图记录logger.error保留完整错误上下文、归一将任意错误统一包装为Error实例、不静默重新抛出而非吞掉异常。这也与通用层绝不要静默吞掉错误、服务端记录详细错误上下文的准则一脉相承。五、输入校验用 Zod 从 schema 推断类型系统边界处的输入校验采用 schema 优先策略——通用层要求绝不信任外部数据API 响应、用户输入、文件内容TypeScript 层将 Zod 作为 schema 校验的标准工具并用z.infer从 schema 推导类型消除 schema 与类型定义的双重维护import { z } from zod const userSchema z.object({ email: z.string().email(), age: z.number().int().min(0).max(150) }) type UserInput z.infertypeof userSchema const validated: UserInput userSchema.parse(input)z.infertypeof userSchema推导出的UserInput等价于手写的{ email: string; age: number }但校验逻辑email 格式、age 为整数且在 0-150 区间只存在于 schema 一处。schema 即单一事实来源single source of truth类型与其永远同步这正是fail fast with clear error messages的具体实现。六、console.log 治理规范 Hook 双重拦截规范的收尾条款直指 Agent 开发中最常见的问题——调试语句残留生产代码中不得保留console.log语句改用合适的日志库如 pino、winston自动检测交由 Hook 完成。这条规范在 ECC 仓库中不仅是纸面约定而是有完整的自动化实现Hook 声明rules/typescript/hooks.md 给出了标准的 Hook 配置方案写入~/.claude/settings.jsonPostToolUse 钩子编辑后自动运行 Prettier 格式化、对.ts/.tsx运行tsc类型检查、对编辑过的文件给出console.log警告Stop 钩子会话结束前对所有修改文件执行console.log审计。仓库内的实际实现仓库的 hooks/hooks.json 中注册了stop:check-console-logStop 钩子描述为Check for console.log in modified files after each response其执行入口是 scripts/hooks/check-console-log.js。从该脚本源码可以看到完整的检测逻辑通过getGitModifiedFiles([\\.tsx?$, \\.jsx?$])获取本次响应中修改过的 JS/TS 文件列表用EXCLUDED_PATTERNS排除测试文件.test./.spec.、配置文件.config.、scripts/目录与__tests__/、__mocks__/目录——这些地方console.log属于有意为之逐一扫描文件内容命中console.log时输出[Hook] WARNING: console.log found in file最后遵循 ECC 的 pass-through 约定将 stdin 原样回写 stdout确保 Stop 钩子的 JSON 校验不因截断失败。与console.log治理配套的还有stop:format-typecheck钩子在每次响应结束时统一对编辑过的 JS/TS 文件执行 Biome/Prettier 格式化与tsc类型检查以及pre:config-protection钩子阻止修改 linter/formatter 配置文件引导 Agent 修复代码而不是放宽配置。七、落地为可执行规范front-matter、ESLint 与检查清单ECC 的规则文件通过 front-matter 声明适用路径使规范天然具备条件触发能力--- paths: - **/*.ts - **/*.tsx - **/*.js - **/*.jsx ---仓库自身的 eslint.config.js 是这套规范的实践缩影启用eslint/js推荐的规则集将no-unused-vars、no-undef设为 error_前缀参数/变量豁免eqeqeq设为 warn忽略.opencode/dist、.cursor、node_modules等生成目录并对*.mjs使用 ESM 的sourceType。项目级校验命令npm run linteslint . markdownlint **/*.md与npm test含validate-rules.js等 CI 脚本共同保证规范文件本身与代码库持续一致。最终通用层提供的质量检查清单rules/common/coding-style.md为每次提交前的自查给出了可勾选标准代码可读且命名良好、函数小于 50 行、文件聚焦且小于 800 行、无超过 4 层的深层嵌套、错误处理完备、无硬编码值、无原地修改。将这七项与本文的 TypeScript 专属规则组合即构成一套可在 Claude Code、Codex、OpenCode、Cursor 等任意 Agent harness 中复用与自动强化的编码规范闭环。【免费下载链接】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),仅供参考
返回列表