AI 写代码总出幺蛾子?一份“禁止清单”让 Bug 少了一半

191 阅读3分钟

上周让 AI 帮我写一个表单页面,生成的代码里有 4 个 any、2 个 moment、1 个 class 组件。

我明明在配置文件里写了"用 TypeScript"、"用 dayjs"、"用函数组件"——为什么 AI 还是犯错?

后来我想明白了:告诉 AI "要做什么",它可能遵守也可能不遵守。但告诉它"不要做什么",它会严格避免。

为什么"禁止"比"要求"有效

flowchart TD
    A[AI生成代码] --> B{有明确禁止规则?}
    B -->|是| C[严格遵守约束<br>生成合规代码]
    B -->|否| D[从训练数据中<br>选择&#34;可能&#34;正确的写法]
    C --> E[高一次通过率<br>~85%]
    D --> F[低一次通过率<br>~40%]
    
    G[正面要求<br>&#34;请用TypeScript&#34;] --> H[AI理解:<br>TS语法合法即可]
    H --> I[可能包含any类型]
    
    J[负面约束<br>&#34;禁止使用any类型&#34;] --> K[AI理解:<br>必须定义具体类型]
    K --> L[消除偷懒空间]

AI 训练数据里见过太多种写法。你说"用 TypeScript",它知道。但它也见过无数用 any 偷懒的代码——如果你不明确禁止,它就可能"学坏"。

正面要求:"请用 TypeScript"
→ AI 理解为:用 TS 语法,但 any 也是合法的 TS ¯\_(ツ)_/¯

负面约束:"禁止使用 any 类型"
→ AI 理解为:必须给每个变量定义具体类型,没有退路

负面约束消除了 AI 的"偷懒空间"。

我的禁止清单(实际在用)

# 禁止事项(违反任何一条都需要修改)

## 类型相关
- ❌ 禁止使用 any(用 unknown 或具体类型)
- ❌ 禁止使用 @ts-ignore(必须解决类型问题)
- ❌ 禁止滥用 as 断言(除非有注释说明原因)
- ❌ 禁止接口函数不定义返回类型

## 组件相关
- ❌ 禁止使用 class 组件
- ❌ 禁止单文件超过 300 行
- ❌ 禁止在组件内直接调用 axios
- ❌ 禁止用 index.tsx 作为业务组件文件名
- ❌ 禁止一个文件导出多个页面级组件

## 样式相关
- ❌ 禁止内联样式(style={{}})
- ❌ 禁止全局 CSS 类名(必须用 CSS Modules)

## 依赖相关
- ❌ 禁止 moment.js(用 dayjs)
- ❌ 禁止 lodash 全量导入(用 lodash/xxx)
- ❌ 禁止 var(用 const/let)
- ❌ 禁止 ==(用 ===)

## 模式相关
- ❌ 禁止 useEffect 内业务逻辑超过 10 行(抽成函数)
- ❌ 禁止 useEffect 缺少依赖项
- ❌ 禁止 try-catch 空 catch(至少 console.error)
- ❌ 禁止硬编码魔法数字(定义常量)

效果

xychart-beta
    title &#34;AI代码生成一次通过率对比&#34;
    x-axis [&#34;无禁止清单&#34;, &#34;有禁止清单&#34;]
    y-axis &#34;通过率(%)&#34; 0 --> 100
    bar [40, 85]
    line [40, 85]

加了禁止清单后,AI 生成代码的"一次通过率":

没有禁止清单:
生成 → 有 any → 改 → 有 moment → 改 → 有 class → 改 → 能用了
一次通过率:~40%

有禁止清单:
生成 → review → 微调业务逻辑 → 能用了
一次通过率:~85%

怎么建立自己的禁止清单

flowchart LR
    A[开始] --> B[翻最近20个MR的review评论]
    B --> C[提取&#34;不要/禁止/改成&#34;类反馈]
    C --> D[去重 + 分类整理]
    D --> E[形成禁止清单]
    
    subgraph &#34;维护流程&#34;
        F[每周根据新CR反馈] --> G[补充1-2条规则]
        H[规则超过30条] --> I[精简合并相似项]
        J[团队review] --> K[提交git版本管理]
    end
    
    E --> F
    E --> H
    G --> J
    I --> J

方法:从 CR 记录里反向提取。

## 3 步建立禁止清单

1. 翻最近 20 个 MR 的 review 评论
2. 提取所有"不要/禁止/改成"类的反馈
3. 去重 + 分类 → 就是你的禁止清单

## 维护方式
- 每周根据新的 CR 反馈补充 1-2 条
- 超过 30 条时精简(合并相似项)
- 团队 review 后提交 git

禁止清单 + ESLint 配合

graph TB
    subgraph &#34;代码质量保障体系&#34;
        A[AI代码生成] --> B{质量检查}
        
        subgraph &#34;语法层面检查&#34;
            C[ESLint规则]
            C1[&#34;@typescript-eslint/no-explicit-any&#34;]
            C2[&#34;@typescript-eslint/ban-ts-comment&#34;]
            C3[&#34;no-var&#34;]
            C4[&#34;eqeqeq&#34;]
            C --> C1
            C --> C2
            C --> C3
            C --> C4
        end
        
        subgraph &#34;设计层面检查&#34;
            D[AI禁止清单]
            D1[&#34;单文件≤300行&#34;]
            D2[&#34;组件内不直接调axios&#34;]
            D3[&#34;禁止class组件&#34;]
            D4[&#34;禁止内联样式&#34;]
            D --> D1
            D --> D2
            D --> D3
            D --> D4
        end
        
        B -->|语法错误| C
        B -->|设计问题| D
        C --> E[自动修复/报错]
        D --> F[生成时避免/人工review]
        E --> G[高质量代码]
        F --> G
    end

ESLint 能自动检查一部分:

{
  "rules": {
    "@typescript-eslint/no-explicit-any": "error",
    "@typescript-eslint/ban-ts-comment": "error",
    "no-var": "error",
    "eqeqeq": "error",
    "no-empty": ["error", { "allowEmptyCatch": false }]
  }
}

ESLint 管不了的("单文件不超过 300 行"、"不要在组件内直接调 axios"),靠 AI 禁止清单兜底。

两者配合:ESLint 管语法层面,禁止清单管设计层面。


一句话总结:与其告诉 AI 100 种"正确的写法",不如告诉它 20 种"禁止的写法"。边界比方向更有效。


💬 你们项目里最常见的"不应该出现但总是出现"的代码是什么?评论区说说。