tRPC 实战:从 REST 到端到端类型安全 API

tRPC 让前后端共享 TypeScript 类型:服务端定义 procedure,客户端自动获得完整类型推导。本文从 Express API 改造实战 tRPC。

最佳实践
应用接口与数据存储连接插画

tRPC 的核心魔法:服务端用 router 定义 procedure,客户端导入 router 类型即获得全链路类型推导——改服务端返回值,前端编译报错。无需 Schema、无需代码生成,全栈 TS 项目的 API 最优解。

为什么是 tRPC

REST 的类型断裂:后端改了响应结构,前端运行时才崩。GraphQL 解决它靠 Schema + 代码生成(重);tRPC 的答案:直接共享 TypeScript 类型——零样板、零生成步骤。

从 Express 到 tRPC

// server/trpc.ts
import { initTRPC } from '@trpc/server';
const t = initTRPC.create();

export const router = t.router;
export const publicProcedure = t.procedure;

// server/routers/user.ts
export const userRouter = router({
  list: publicProcedure.query(() => db.users.findAll()),
  byId: publicProcedure
    .input(z.string())   // zod 校验输入
    .query(({ input }) => db.users.findById(input)),
  create: publicProcedure
    .input(z.object({ name: z.string(), email: z.string().email() }))
    .mutation(({ input }) => db.users.create(input)),
});

// server/index.ts
export const appRouter = router({ user: userRouter });
export type AppRouter = typeof appRouter;   // 类型导出是全链路的钥匙
// client:导入类型(只导入 type,零运行时代码)
import type { AppRouter } from '../server';
const trpc = createTRPCClient<AppRouter>({ links: [httpBatchLink({ url: '/trpc' })] });

const user = await trpc.user.byId.query('123');
//    ^? 完整类型推导:参数类型、返回值类型、自动补全

模块化结构

路由按领域拆分(userRouter/postRouter),mergeRouters 或嵌套组合。中间件机制(t.middleware)实现认证:

const protectedProcedure = publicProcedure.use(async ({ ctx, next }) => {
  if (!ctx.user) throw new TRPCError({ code: 'UNAUTHORIZED' });
  return next({ ctx: { user: ctx.user } });
});

React 集成

@trpc/react-query 把 procedure 包装成 TanStack Query hooks——trpc.user.list.useQuery() 直接获得缓存/加载态/类型三全。

边界

  • 仅适合前后端同 TS 仓库(monorepo 最理想);
  • 对外公开 API 仍需 REST/GraphQL——tRPC 是"内部 API"的王者;
  • 与 Next.js App Router / Hono 的 RPC 模式存在竞争——理念相同。

验证接口上线后的延迟与错误

tRPC 实战完成开发验证后,可选一条包含数据库或外部调用的业务路径接入观测云。按 Node.js APM 文档确认探针初始化顺序与框架兼容性,检查请求及下游 Span 是否连续,再按文档注入日志关联字段。以路由模板或稳定的操作名聚合,避免用用户 ID、动态 URL 或完整 GraphQL 查询作为高基数标签。

接入文档:Node.js APM 接入 · 日志采集 · 日志与链路关联。

常见问题(FAQ)

Q:tRPC 和 GraphQL 怎么选?

全栈 TS 内部通信:tRPC(零样板);跨语言、对外 API、复杂查询图:GraphQL。

Q:输入校验用什么?

Zod 是标准搭配(procedure 的 input 校验器),Valibot/TypeBox 也可——校验结果同时成为输入类型。

Q:错误怎么处理?

TRPCError 带 code(NOT_FOUND/FORBIDDEN...)抛出,客户端按 code 分支——错误也有类型。


参考文档

本文依据公开文档整理,示例需按项目依赖版本验证;不将文档中的性能描述视为本项目实测结果。

延伸阅读

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台