TypeScript架构工程化

前端类型安全接口的三种姿势

2024-11-156 min

背景

前后端协作中,接口类型安全是一个老生常谈的问题。类型不一致会导致:

  • 后端改了接口,前端没同步,报错难查
  • 手动维护类型,工作量大且容易遗漏
  • 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 文档
  • 生成工具链需要团队熟悉

适用场景

中大型团队,多技术栈协作,接口数量多且变更频繁的项目。


三种方案对比

维度手写类型tRPCOpenAPI 代码生成
类型安全程度⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
技术栈灵活性⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
维护成本⭐⭐(高)⭐⭐⭐⭐⭐⭐⭐⭐⭐
AI Agent 友好度⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
上手难度⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
适用项目规模

我们最终的选择

在大型团队中,我们选择了 OpenAPI 代码生成方案,原因是:

  1. 技术栈无关:后端可能是 Java、Go、Python,不强耦合
  2. 规范可落地:有明确的文档标准,后端改接口必须更新文档
  3. TanStack Query 集成:开箱即用的缓存、重试、乐观更新
  4. AI Agent 友好:生成的代码有丰富类型注解,AI 能读懂接口语义

实际上,最好的方案取决于团队情况。小团队用 tRPC 更直接,大团队用 OpenAPI 更规范。

Saylo - 全栈开发工程师