則:從不可變性與 Zod 校驗到 Hook 自動檢測)
ECC 的 TypeScript/JavaScript 編碼風格規(guī)則從不可變性與 Zod 校驗到 Hook 自動檢測【免費下載鏈接】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 倉庫中的 Cursor 規(guī)則文件.cursor/rules/typescript-coding-style.md展開系統(tǒng)講解其中四條 TypeScript/JavaScript 編碼風格約定——不可變更新、async/await 錯誤處理、Zod 輸入校驗與console.log禁令——的完整寫法并結(jié)合倉庫源碼剖析這些規(guī)則如何通過 Hook 機制scripts/hooks/check-console-log.js等在 Agent 會話中自動執(zhí)行幫助你既能在人寫代碼時直接復(fù)用這套規(guī)范也理解其底層自動化實現(xiàn)。規(guī)則文件的定位Cursor Rules 的通用 語言兩層結(jié)構(gòu)ECC 倉庫為 Cursor 提供了一組可版本化的編碼規(guī)則位于 .cursor/rules/ 目錄。該目錄下按通用common- 語言專屬兩層組織.cursor/rules/common-coding-style.mdalwaysApply: true所有語言共享的編碼風格基線不可變性、錯誤處理、輸入校驗、代碼質(zhì)量清單.cursor/rules/typescript-coding-style.mdTypeScript/JavaScript 專屬擴展開頭明確寫著 This file extends the common coding style rule with TypeScript/JavaScript specific content.。后者的 YAML front matter 定義了它的加載條件--- description: TypeScript coding style extending common rules globs: [**/*.ts, **/*.tsx, **/*.js, **/*.jsx] alwaysApply: false ---三個字段的作用字段取值含義descriptionTypeScript coding style extending common rules規(guī)則描述供規(guī)則列表檢索展示globs**/*.ts、**/*.tsx、**/*.js、**/*.jsx僅當上下文涉及這四類文件時觸發(fā)注入alwaysApplyfalse非全局常駐按 glob 匹配按需生效這種按文件類型觸發(fā)的設(shè)計正是 Cursor Rules 的核心機制與alwaysApply: true的通用規(guī)則互補避免把 TS 專屬內(nèi)容塞進每個文件的上下文中從而節(jié)省 token、減少無關(guān)干擾。核心約束一不可變更新Immutability規(guī)則文件給出的標準范式是禁止原地修改用 spread 返回新對象// WRONG: Mutation function updateUser(user, name) { user.name name // MUTATION! return user } // CORRECT: Immutability function updateUser(user, name) { return { ...user, name } }這條約束并非 TS 特有——它在 .cursor/rules/common-coding-style.md 中被標記為CRITICAL并給出理由不可變數(shù)據(jù)能消除隱藏副作用、降低調(diào)試成本、支持安全并發(fā)。同一文件還配套了量化約束函數(shù) 50 行、文件 800 行、嵌套不超過 4 層、無硬編碼值作為標記工作完成前的檢查清單。值得注意的是倉庫在同一規(guī)范下存在一個擴展版rules/typescript/coding-style.md。它在 Cursor 版的四個章節(jié)之上前置了更完整的類型設(shè)計約定例如公共 API 顯式類型導(dǎo)出函數(shù)必須標注參數(shù)與返回類型局部變量可交給推斷interface vs type可能被擴展/實現(xiàn)的形狀用interface聯(lián)合、交叉、映射、工具類型用type優(yōu)先字符串字面量聯(lián)合而非enum避免any外部/不可信輸入用unknown再安全收窄泛型用于類型取決于調(diào)用方的場景// WRONG: any removes type safety function getErrorMessage(error: any) { return error.message } // CORRECT: unknown forces safe narrowing function getErrorMessage(error: unknown): string { if (error instanceof Error) { return error.message } return Unexpected error }React Props用命名interface定義 props、顯式標注回調(diào)類型、無特殊理由不用React.FC純 JS 文件在無法遷移到 TS 時用 JSDoc 表達類型且要求 JSDoc 與運行時行為保持一致。從源碼結(jié)構(gòu)看.cursor/rules/Cursor 側(cè)與rules/Claude/通用側(cè)兩份規(guī)則內(nèi)容高度同構(gòu)、互為鏡像ECC 通過這種雙份維護讓不同 Agent 客戶端加載各自格式的同一套規(guī)范。寫作 TS 代碼時建議以擴展版為完整清單先過類型設(shè)計再過下文的四條實操約束。核心約束二async/await try-catch 錯誤處理規(guī)則文件要求異步操作統(tǒng)一使用 async/await 配 try-catch而不是裸.then/.catchtry { const result await riskyOperation() return result } catch (error) { console.error(Operation failed:, error) throw new Error(Detailed user-friendly message) }關(guān)鍵點在于兩層信息分離console.error落詳細錯誤上下文服務(wù)端/開發(fā)側(cè)可見重新拋出的Error攜帶面向用戶的友好信息UI 側(cè)可見。這與通用規(guī)則中UI 面向代碼給友好信息、服務(wù)端記詳細上下文、絕不靜默吞錯的要求一一對應(yīng)。擴展版 rules/typescript/coding-style.md 把該模式升級為完整可運行示例catch 參數(shù)標注unknown、通過instanceof Error收窄、用可替換的生產(chǎn)級 logger 接口注釋建議 pino/winston替代console.errorasync 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)) } }核心約束三Zod 模式化輸入校驗規(guī)則文件指定 Zod 作為邊界校驗的標準方案import { z } from zod const schema z.object({ email: z.string().email(), age: z.number().int().min(0).max(150) }) const validated schema.parse(input)配套的通用規(guī)則要求在系統(tǒng)邊界校驗所有輸入、快速失敗、永不信任外部數(shù)據(jù)API 響應(yīng)、用戶輸入、文件內(nèi)容。擴展版進一步給出了類型聯(lián)動寫法——用z.infer從 schema 推導(dǎo)輸入類型使校驗邏輯與類型定義單一來源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)這意味著parse成功后返回值的類型即UserInput下游函數(shù)簽名可以直接消費該類型無需手寫一遍字段聲明。核心約束四console.log 禁令與自動檢測規(guī)則文件第四條約定生產(chǎn)代碼中不允許console.log語句應(yīng)使用正規(guī)的 logging 庫替代See hooks for automatic detection——即該約定不只靠人遵守而是由 Hook 機制自動檢測。這一見 Hook的指向在倉庫中有完整的實現(xiàn)鏈路可以印證1. 規(guī)則側(cè)的聲明.cursor/rules/typescript-hooks.md.cursor/rules/typescript-hooks.md 與編碼風格規(guī)則使用完全相同的globs和alwaysApply: false聲明了 TypeScript 文件相關(guān)的 HookPostToolUse配置于~/.claude/settings.jsonPrettier 編輯后自動格式化、編輯.ts/.tsx后運行tsc類型檢查、對編輯文件中的console.log發(fā)出警告Stop會話響應(yīng)結(jié)束前對所有已修改文件做console.log審計。2. 實現(xiàn)側(cè)的落地check-console-log.jsStop 鉤子的實際實現(xiàn)位于 scripts/hooks/check-console-log.js。閱讀源碼可以看到幾個工程細節(jié)檢測范圍通過getGitModifiedFiles([\\.tsx?$, \\.jsx?$])只掃描本輪 git 已修改的 JS/TS 文件而非全倉庫控制開銷豁免模式EXCLUDED_PATTERNS排除了測試與腳本場景——.test./.spec.文件、*.config.js/ts、scripts/目錄、__tests__/、__mocks__/因為在這些地方console.log往往是有意為之只警告不阻斷命中后僅log([Hook] WARNING: console.log found in ...)并提示提交前移除退出碼保持 0符合 hooks 架構(gòu)中Stop 鉤子可分析但不能阻斷的定位ECC 透傳約定stdin 原樣回寫到 stdoutpassThroughAndExit且設(shè)置了 1MB 的 stdin 上限——超限的截斷 JSON 不再回顯以免觸發(fā) harness 的 JSON 校驗失敗源碼注釋明確指向 issue #2090。該鉤子在 hooks/hooks.json 的Stop數(shù)組中以stop:check-console-log注冊運行于standard,strict配置檔位同一數(shù)組中還有stop:format-typecheck批量 Prettier/Biome 格式化 tsc類型檢查注釋說明在 Stop 時一次性運行而非每次 Edit 后。3. 使用與開關(guān)按 hooks/README.md 的說明這套 Hook 不建議手工粘貼hooks.json而是通過安裝器解析安裝bash ./install.sh --target claude --modules hooks-runtime --enable-hookspwsh -File .\install.ps1 --target claude --modules hooks-runtime --enable-hooks安裝后可用環(huán)境變量控制行為而不改配置ECC_HOOKS_ENABLED總開關(guān)、ECC_HOOK_PROFILEminimal | standard | strict默認standard、ECC_DISABLED_HOOKS按 ID 逗號分隔禁用特定鉤子例如可禁用 console 相關(guān)檢查。4. 倉庫自身的 lint 佐證ECC 倉庫對 JS/TS 的靜態(tài)檢查基線見 eslint.config.jsecmaVersion: 2022、默認sourceType: commonjs.mjs單獨聲明為 module啟用no-unused-vars^_前綴豁免、no-undeferror與eqeqeqwarn并 ignore 了.cursor/**、workflows/**/*.workflow.*等目錄——這也解釋了為何.cursor/rules/下的規(guī)則腳本不受本倉庫 lint 約束??梢酝茢嘁?guī)則文檔中使用正規(guī) logging 庫而非 console.log的要求最終由 ESLintno-console類規(guī)則可自定義 Stop 鉤子雙層兜底。規(guī)則全景四條約定的完整繼承關(guān)系約定通用基線common-coding-style.mdTS/JS 專屬typescript-coding-style.md擴展版rules/typescript/coding-style.md不可變CRITICALcreate new, never mutatespread 更新范式增加ReadonlyT參數(shù)標注錯誤處理顯式處理、友好信息 詳細日志、不靜默吞錯async/await try-catchunknown收窄 logger 接口輸入校驗邊界校驗、快速失敗、不信任外部數(shù)據(jù)Zod schema 示例增加z.infer類型推導(dǎo)console.log未單列生產(chǎn)禁用、用 logging 庫、Hook 自動檢測同左類型設(shè)計未涉及未涉及公共 API 類型、interface/type 取舍、禁 any、Props、JSDoc小結(jié)如何把這套規(guī)則用在自己的項目里直接復(fù)用規(guī)則文件.cursor/rules/下common 語言兩層規(guī)則是純 Markdown YAML front matter可整體拷貝到目標倉庫的 Cursor 規(guī)則目錄globs與alwaysApply字段的組合方式全局基線常駐、語言規(guī)則按文件類型觸發(fā)值得照搬規(guī)范 自動化閉環(huán)ECC 的示范價值在于每條約定都有執(zhí)行器——console.log 有scripts/hooks/check-console-log.js格式化/類型檢查有stop:format-typecheck。落地規(guī)則時同步配置對應(yīng) lint/鉤子比純文檔約束有效得多注意適用前提Hook 部分依賴 Claude Code 的 hooks 機制PreToolUse/PostToolUse/Stop事件PreToolUse 可用退出碼 2 阻斷PostToolUse/Stop 只分析不阻斷且需通過install.sh --target claude --modules hooks-runtime --enable-hooks安裝以獲得按實際 Claude 根目錄重寫的命令minimal/standard/strict三檔 profile 決定檢查嚴格度默認standard。綜合來看.cursor/rules/typescript-coding-style.md本身是一份高度精煉的 Agent 規(guī)則四條約定覆蓋了 TS/JS 生產(chǎn)代碼中最常見的四類質(zhì)量風險而 scripts/hooks/check-console-log.js、hooks/hooks.json 與 rules/typescript/coding-style.md 則分別提供了它的自動化執(zhí)行與類型層擴展三者共同構(gòu)成了 ECC 規(guī)則即代碼風格體系在 TypeScript 場景下的完整落點?!久赓M下載鏈接】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創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考