背景
前后端协作中,接口类型安全是一个老生常谈的问题。类型不一致会导致:
- 后端改了接口,前端没同步,报错难查
- 手动维护类型,工作量大且容易遗漏
- AI Agent 无法准确理解接口语义
我们调研了三种主流方案,来看看各自的优劣。
方案一:手写类型(传统做法)
做法
前端手动编写接口类型定义:
// types/api.ts
interface SaveHrRequest {
name: string;
avatar: string;
}
interface SaveHrResponse {
code: number;
message: string;
data: null;
}
async function saveHr(params: SaveHrRequest): Promise<SaveHrResponse> {
return fetch('/api/business/settings/hr/save', {
method: 'POST',
body: JSON.stringify(params),
}).then(r => r.json());
}优点
- 简单直接,小项目上手快
- 完全可控,不依赖任何工具链
缺点
- 维护成本高:后端改接口,前端必须手动同步
- 容易遗漏:类型和接口文档容易脱节
- AI Agent 不友好:没有标准化的接口描述,AI 难以理解
适用场景
小型项目、一次性脚本、接口数量 < 10 个的简单场景。
方案二:tRPC(端到端类型安全)
做法
tRPC 通过 TypeScript 的类型推断,实现前后端无缝类型共享:
const appRouter = router({
saveHr: publicProcedure
.input(z.object({ name: z.string(), avatar: z.string() }))
.mutation(async ({ input }) => {
await db.hr.create({ data: input });
}),
});
export type AppRouter = typeof appRouter;优点
- 真正的端到端类型安全:后端类型变化,前端立即报错
- 无代码生成:类型推断,无需运行命令
- AI Agent 友好:类型即文档,语义清晰
缺点
- 强耦合:前后端必须用同一套技术栈(Node.js/TypeScript)
- 学习曲线:需要理解 tRPC 的 procedure 模式
适用场景
全栈 TypeScript 项目,前后端技术栈统一的小型到中型团队。
方案三:OpenAPI 代码生成(我们选择的方案)
做法
后端维护 OpenAPI 文档,前端用 qxun-api-generator 自动生成 TypeScript 类型 + TanStack Query hooks:
const { mutateAsync: saveHr } = useMutation({
mutationFn: (params: BusinessSettingsHrSaveValidate) =>
DefaultApiFactory().saveHr({ businessSettingsHrSaveValidate: params }),
});优点
- 规范化:替代"口头对接"模式,后台改了接口前端类型立即报错
- 模块化:按业务域自动分模块生成接口 + TS 类型
- 工程化:自动生成类型 + TanStack Query 开箱即用的缓存/重试/乐观更新
- AI Agent 友好:丰富的类型注解和 JSDoc 注释
- 技术栈无关:后端可以是任何语言,只需提供 OpenAPI 文档
缺点
- 需要后端配合维护 OpenAPI 文档
- 生成工具链需要团队熟悉
适用场景
中大型团队,多技术栈协作,接口数量多且变更频繁的项目。
三种方案对比
| 维度 | 手写类型 | tRPC | OpenAPI 代码生成 |
|---|---|---|---|
| 类型安全程度 | ⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| 技术栈灵活性 | ⭐⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐⭐ |
| 维护成本 | ⭐⭐(高) | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
| AI Agent 友好度 | ⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
| 上手难度 | ⭐⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐ |
| 适用项目规模 | 小 | 中 | 大 |
我们最终的选择
在大型团队中,我们选择了 OpenAPI 代码生成方案,原因是:
- 技术栈无关:后端可能是 Java、Go、Python,不强耦合
- 规范可落地:有明确的文档标准,后端改接口必须更新文档
- TanStack Query 集成:开箱即用的缓存、重试、乐观更新
- AI Agent 友好:生成的代码有丰富类型注解,AI 能读懂接口语义
实际上,最好的方案取决于团队情况。小团队用 tRPC 更直接,大团队用 OpenAPI 更规范。