当开发者过度依赖「感觉」而非系统化工程方法时,代码会逐渐滑向不可维护的深渊。Vibe Coding 是一种借助 AI 快速生成代码的开发方式,但它也极易催生三类典型的工程反模式:缺失类型边界、无测试防护、以及硬编码环路。这些反模式并非无解,通过建立明确的工程边界与自动化防护机制,团队可以在享受 AI 开发效率的同时保持代码库的健康度。

缺失类型边界:Any 类型蔓延与接口失控

Vibe Coding 场景中最常见的类型问题,是开发者接受 AI 生成的代码而不加审查,导致 any 类型在代码库中蔓延。TypeScript 的类型系统本意是提供编译期安全保障,但当函数参数、返回值、变量声明都使用 any 时,这层保护形同虚设。根据行业实践,当一个中型项目(万行级别)中 any 类型占比超过 15% 时,类型检查对开发体验的提升将显著下降,开发者会逐渐忽略类型错误警告,形成「警告疲劳」。

更危险的是隐式 any 的传播。在没有显式标注的函数参数、箭头函数参数、以及第三方库返回值中,TypeScript 可能推断出 any 并保持沉默。推荐的做法是启用 TypeScript 编译选项中的 noImplicitAny: true,强制要求所有隐式 any 都要显式声明。此外,定义核心领域的接口(Interface)并通过 ESLint 规则限制 // @ts-ignore// @ts-expect-error 的使用数量,单个文件内不超过两处,全局每日新增不超过五处。

针对 AI 生成的代码,建议设立「类型门禁」:任何超过五十行的 AI 生成代码块,在合并前必须经过人工类型审查。可以使用 typescript-eslintno-explicit-any 规则作为 CI 阶段的强制检查。对于第三方 API 响应,建议使用 Zod 或 io-ts 在运行时验证类型,而非仅依赖编译期检查,这相当于在类型边界之外增加了一道运行时防线。

无测试防护:单元测试覆盖率低于基准线的风险

Vibe Coding 的另一个典型问题是对测试的忽视。AI 生成的代码往往功能导向,缺乏对应的测试用例。业界共识是,核心业务逻辑的单元测试覆盖率应保持在 70% 以上,基础设施层(如数据库操作、缓存层)应达到 80% 以上。当覆盖率低于 50% 时,代码重构的风险将急剧上升 —— 开发者无法判断修改是否破坏了现有功能。

对于 Vibe Coding 项目,建议采用「测试骨架优先」策略:在接受 AI 生成的代码前,先由人工或 AI 生成测试占位符,再让 AI 补充测试实现。这确保了每个新函数都有对应的测试文件。测试文件命名应遵循 *.test.ts*.spec.ts 的约定,与源文件一一对应。

更实用的做法是建立「冒烟测试清单」。对于每个新功能,至少要验证三类边界条件:空输入(null、undefined、空数组)、极端值(超长字符串、超大数字)、以及错误路径(网络超时、权限拒绝)。这些测试不需要复杂的 mock 框架,可以使用 Jest 的 describe.each 或 Vitest 的表格测试语法快速生成。例如,一个处理用户列表的函数应该覆盖空数组、单元素数组、以及包含重复元素的数组三种场景。

CI 流水线中应强制执行测试门禁。建议配置如下参数:测试失败时阻断合并;测试覆盖率低于阈值时发出警告(阈值建议为核心层 70%、工具层 60%);新增代码必须包含对应的测试用例。这些检查可以通过 GitHub Actions 或 GitLab CI 的 job 配置实现,核心逻辑是让测试覆盖率成为代码合并的硬性前提。

硬编码环路:循环逻辑缺乏抽象与复用

第三类反模式是硬编码环路(Hardcoded Loops),即在业务代码中直接写死循环逻辑,而不是封装为可复用的函数或使用高阶函数。在 Vibe Coding 场景下,AI 经常生成类似 for (let i = 0; i < arr.length; i++) 的原始循环,而非使用 mapfilterreduce 等声明式写法。这种代码的可读性差,且难以测试。

具体问题包括:循环内部包含复杂的副作用逻辑(如直接调用 API、修改全局状态);循环条件与业务规则耦合,无法通过参数配置;以及相同或相似的循环逻辑在多个文件中重复出现。推荐的修复策略是将循环逻辑封装为纯函数,接受明确的输入并返回明确的输出。纯函数的优势在于可以单独测试 —— 给定相同输入,必然得到相同输出,这大幅降低了测试复杂度。

对于常见的数组操作,建议建立项目级别的工具库(Utility Functions),封装以下高阶函数:数据转换(transform)、条件过滤(filter)、分页切片(paginate)、以及分组聚合(groupBy)。每个工具函数都应该有对应的单元测试和 TypeScript 类型签名。例如,不要在业务代码中写 for (let i = 0; i < items.length; i++),而是调用 paginate(items, page, pageSize),这样循环逻辑被隔离到工具层,业务代码只关注业务语义。

另一个实用的工程实践是「循环审计」。每季度对代码库进行一次循环逻辑审计,识别出超过二十行的循环体、嵌套超过两层的循环、以及在循环内部调用异步函数的代码块。这些都是潜在的代码异味(Code Smell),需要通过重构来改善。审计结果应记录在技术债务看板中,指定专人负责跟进。

防护清单与工程参数

综合以上三类反模式,团队可以建立以下可落地的工程参数。类型边界方面:启用 noImplicitAny: true;ESLint 规则 no-explicit-any 在 CI 中强制执行;核心接口文件不超过五个,集中在 src/types 目录下。测试防护方面:单元测试覆盖率核心层 70% 以上、工具层 60% 以上;每个导出函数至少有一个对应的测试用例;CI 中配置 npm test -- --coverage 并设置阈值检查。循环抽象方面:禁止在业务代码中直接写原始 for 循环;优先使用 mapfilterreduce 等高阶函数;建立项目级工具库并维护对应的测试文件。

除此之外,代码审查流程中应加入「反模式检查」环节。审查者需要确认:AI 生成的代码是否存在 any 类型;新增函数是否有对应的测试用例;循环逻辑是否已抽象为可复用函数。这不是否定 AI 辅助开发的价值,而是为其设立必要的工程边界。

Vibe Coding 本身并非问题,问题在于在没有工程防护的情况下盲目接受 AI 生成的代码。通过类型边界、测试覆盖率、循环抽象三个维度的持续投入,团队可以在保持开发速度的同时确保代码质量。工程纪律不是束缚,而是让「感觉驱动」的代码走向「可维护、可测试、可演进」的正轨。

资料来源:本文部分反模式定义参考 VeeCode 平台文档中的 Anti-Patterns to Avoid 相关内容。