在 Cursor 或 Copilot 里按下 Tab,30 行 TypeScript 很快就出来了。缩进漂亮,函数名也像项目里的写法。运行后,提交按钮能连续点击,库存校验还没结束,订单请求已经发出;某个 useEffect 又把状态同步写成了死循环。
到了 2026 年,即便模型迭代到 GPT-5,类似问题仍会出现。代码补全根据当前输入继续预测,业务条件缺一块,生成结果就可能沿着错误方向写得很完整。一则介绍 AI 编程 L1-L5 的资料把代码补全称作“智能输入助手”,代表工具包括 GitHub Copilot、Tabby,优势是加快编码、减少拼写错误。这个比喻很准确:续写很快,前提是它看到了该看的代码。
先看这个订单结算函数
假设一个 React 订单结算组件要处理三件事:
- 根据用户地址实时计算税率;
- 根据商品 ID 异步校验库存;
- 提交订单时执行乐观更新。
你刚写下:
const handleCheckout = async () => {
AI 接着补出一个 await api.submit()。单看这个函数没什么大错,但它漏掉了 useOrderStore 里的状态锁。请求发出后按钮仍可点击,用户可能重复提交。
这类问题靠多按几次 Tab 很难解决。每次补全都在相似的输入上重新猜,缺失的条件并不会自动出现。
它到底看见了哪些文件
状态定义在 store.ts,接口类型放在 api.d.ts,当前编辑器里只有 Checkout.tsx。此时先检查本次补全实际引用了哪些内容,别因为仓库已经打开,就默认工具理解了全部代码。
在 Cursor 中,可以使用 @Codebase 引入代码库信息,也可以直接打开并引用相关文件。至少把状态定义、接口签名和项目已有的工具函数放进当前上下文。
还有一个很直观的判断办法:项目明明在 utils/hooks.ts 里提供了 useDebounce,AI 却现场写了一个简化版 debounce。这通常说明现成实现没有进入它的视线。继续改 Prompt 之前,先把缺失文件补进来。
关于一次补全请求如何组织代码库信息,可以参考《AI 生成代码的生命周期》对 Cody 的拆解。代码库理解依赖上下文组织,并非打开插件后自然完成。
把需求写成执行顺序
“帮我实现提交逻辑”看似清楚,实际留下了太多空白:先校验什么、哪些请求并行、冲突怎么处理,模型都要自己猜。
与其写一句宽泛要求,不如直接留下可执行的注释:
// 提交订单:先调用 store.setLock(true)
// 随后并行请求 /validate-stock 和 /calc-tax
// 最后提交订单,沿用现有乐观更新与回滚逻辑,并处理 409 冲突
精简 Prompt 不等于只写一句。删掉“完善、健壮、优雅”这类无法验收的词,把调用顺序、依赖关系和异常分支写出来,才算真正精简。AI 要猜的地方少了,逻辑跑偏也更容易被发现。
仓库里的正确样板,比长解释管用
如果项目统一使用 Result 类型处理错误,AI 却习惯生成 try-catch,单纯提醒“遵循项目规范”往往不够。给它一个已经运行过的同类函数更直接:
// 参考 UserProfile.tsx 中的 handleUpdate 模式
// 实现 handleCheckout,并保留相同的乐观更新和回滚逻辑
这类 Few-Shot 示例最好与当前任务结构接近:都有异步请求、状态变更和失败回滚。只贴一段视觉风格相似、业务流程无关的组件,帮助有限。
样板的价值也不只在代码风格。它能让 AI 看到项目如何调用 store、怎样封装接口,以及错误最终交给哪一层处理。
把禁用项提前写进 Prompt
模型会优先选择训练数据里常见的写法,项目规范却未必允许。比如 React 19+ 项目已经明确在相关场景使用 use 或 Server Actions,并禁止用 useEffect 同步状态,就要直接写清楚。
// 禁止使用 useEffect 处理状态同步
// 不要直接修改 store,必须通过 dispatch
// 所有 API 调用都要包在 withErrorHandling 中
“采用现代写法”或“注意最佳实践”无法形成明确的检查标准。具体到 API、调用方式和禁用行为,生成后才能逐条核对。发现违规时,也只需退回对应片段,不必推翻整个函数。
50 行一次收,评审一定吃力
复杂逻辑不适合一次生成 50 行再统一验收。更稳妥的节奏是:状态定义 → 确认 → 逻辑处理 → 确认 → UI 绑定。
每一段都可以直接看 Diff。状态字段错了,就先修字段;异步顺序错了,只重写请求部分。比如明确告诉 AI:
第 12 行忽略了库存校验的异步顺序,请只重新生成这个片段。
这比删掉全部代码再按一次 Tab 有效。具体纠正会成为当前 Session 的新增上下文,后续补全至少有了明确参照。生成速度通常不是瓶颈,逐段 Review 才决定这些代码能不能进仓库。
卡住时,就查这五件事
- 当前上下文里有
store.ts、api.d.ts和相关工具函数吗? - Prompt 是否写清了调用顺序、依赖关系和异常分支?
- 仓库里有没有可引用的同类正确实现?
- 禁用的 API 和必须遵守的调用方式是否已经列明?
- 这次是在分段看 Diff,还是准备一次接收几十行代码?
第一项答不清,就先补文件;第二项仍然模糊,就别急着让 AI 写完整函数。代码补全可以从智能输入助手走向更深的协作,但业务条件仍要有人交代,每一段代码也仍要有人验收。