AI 写出来 TypeScript 类型错误

AI 出的代码过不了类型检查——通常是类型猜错、any 转换、漏掉泛型。

Cursor / Claude Code / Copilot 写完一段 TypeScript 直接 commit,你跑 tsc --noEmit 看到一堆 TS2322: Type 'string' is not assignable to type 'number'TS2339: Property 'foo' does not exist on type 'unknown'。AI 模型没有运行时类型反射能力,只能凭训练数据猜接口形状,遇到 generics、union types、third-party .d.ts 时尤其容易出错。这篇拆 5 个高频根因,给出让 AI 自动在循环里修类型错的工作流。

常见原因

按命中率从高到低排序。

1. AI 猜了它没读过的类型签名

最常见:调用第三方库时,AI 凭记忆里旧版本的签名写代码,但你装的是新版本,API 已经改了。

// AI 写的(旧 stripe SDK)
const charge = await stripe.charges.create({ amount: 1000, currency: "usd" });
// 新 SDK(PaymentIntents 时代)
// → TS2554: Expected 0 arguments, but got 1

如何判断:错误码是 TS2554(参数数量错) / TS2345(参数类型错) / TS2339(属性不存在),且发生在第三方库调用点。

2. 强转 any / as unknown as T 掩盖真错误

AI 跑不通就 as anyas unknown as Foo 一刀切,编译过了但运行时直接 crash。

const data = (response as any).user.email;   // response 其实是 { error: string }
// 编译通过,运行时 TypeError: Cannot read property 'email' of undefined

如何判断grep -n "as any\|as unknown as" src/ 数一下出现次数;AI 写的代码段里 > 2 处基本都是回避问题。

3. 泛型参数漏写或写错

Array.prototype.reduceuseStateuseRef、Map / Set、自定义 generic function——AI 经常默认 TypeScript 能推出来,但实际推成 never[]unknown

// AI 写的
const items = [].reduce((acc, x) => {
  acc.push(x.name);   // TS2339: Property 'push' does not exist on type 'never'
  return acc;
}, []);

// 正确
const items = [] as string[];
// 或
const items = [].reduce<string[]>((acc, x) => { acc.push(x.name); return acc; }, []);

如何判断:错误信息里出现 never / unknown / Argument of type 'X' is not assignable to parameter of type 'never'

4. strict 模式下没处理 null / undefined

AI 训练里大量旧代码没开 strictNullChecks,结果生成的代码假设字段一定存在。开了 strict 之后 TS2532: Object is possibly 'undefined' 满天飞。

function getEmail(user: User | null) {
  return user.email;   // TS18047: 'user' is possibly 'null'
}

如何判断:错误码 TS2531 / TS2532 / TS18047 / TS18048,且 tsconfig.json"strict": true

5. import 类型与值混用 / 缺 import type

verbatimModuleSyntaxisolatedModules 开启后,type-only import 必须用 import type,AI 经常忘。

import { User } from "./types";   // 如果 User 只是 type,TS1484 / runtime "undefined"
// 正确
import type { User } from "./types";

如何判断:错误码 TS1484: 'User' is a type and must be imported using a type-only import 或运行时 User is undefined

最短修复路径

按收益排序。Step 1+2+3 是 AI 类型错误的标准修复闭环。

Step 1:跑 tsc --noEmit 把所有错一次性暴露

不要看到第一个错就让 AI 改。一次性输出全部,让 AI 看见全貌:

npx tsc --noEmit --pretty false > ts-errors.txt
wc -l ts-errors.txt

--pretty false 关闭彩色,方便贴给 AI;--incremental false 可以保证每次重新算(如果 .tsbuildinfo 让你怀疑结果)。

Step 2:把原文错误(含文件名:行号)整段贴回 AI

不要复述、不要总结。原文越完整,AI 修得越准:

我跑 tsc --noEmit 得到以下错误,请按以下要求修:
1. 不准用 as any / as unknown as
2. 不准为了通过加 // @ts-ignore / // @ts-expect-error
3. 如果某个第三方库的类型确实有问题,告诉我该升级哪个版本或装哪个 @types/*
4. 修完贴一段 diff,并解释每个改动的原因

错误日志:
src/api/user.ts:34:7 - error TS2322: Type 'string' is not assignable to type 'number'.
src/api/user.ts:41:12 - error TS2339: Property 'email' does not exist on type 'unknown'.
[完整粘贴]

Step 3:让 AI 在循环里自我验证(agent loop)

Claude Code / Cursor Composer / Aider 都支持运行命令。配置成”改完代码必须跑 tsc”:

你要在本任务里:
1. 修复类型错误
2. 每次改完执行 `npx tsc --noEmit`
3. 如果还有错,继续修,最多 5 轮
4. 5 轮后还修不完,停下来告诉我哪些错你不会修,列出原文

Aider 直接加 --auto-test --test-cmd "npx tsc --noEmit"

Step 4:第三方库类型不对就找 @types/* 或上游 .d.ts

很多 npm 包类型由社区维护:

npm install -D @types/node @types/react @types/lodash
# 看看库自己有没有打包类型
npm view <pkg> types
# 没 @types 也没自带就让 AI 写个最小 declaration
echo 'declare module "untyped-lib";' > src/types/untyped-lib.d.ts

避免 as any——临时声明 module 至少未来可逐步补全。

Step 5:常见错误码 → 修复方式对照表

错误码含义修复方向
TS2322类型不匹配检查赋值两端类型,加显式 type 注解
TS2339属性不存在type 太宽,需要类型守卫 / in 检查 / 断言
TS2345参数类型不对看函数签名,确认调用方传值类型
TS2554参数数量不对库版本变了,查 changelog
TS2531/2532null/undefined 未处理if (x) 守卫 / x?.foo / x!
TS7006隐式 any给参数显式类型
TS2304找不到名字import 漏了 / @types/* 没装
TS1484type-only import改成 import type
TS2741缺必需属性检查对象字面量,补齐字段

预防建议

  • tsc --noEmit 放进 AI 的 agent loop / pre-commit hook,类型不过直接拦住
  • CLAUDE.md / .cursorrules 写死:禁止 as any、禁止 @ts-ignore、禁止 @ts-expect-error 不带原因注释
  • tsconfig.json"strict": true + "noUncheckedIndexedAccess": true,让 AI 必须显式处理 null
  • code review 时搜 as any / // @ts-,零容忍
  • 升级第三方依赖时让 AI 同步检查 .d.ts 是否需要换 @types/* 版本
  • 使用 tsc --noEmit --extendedDiagnostics 分析 type 性能,避免 AI 写出递归 union 拖垮编译

相关阅读

标签: #AI 编程 #排查 #排查