tRPC

tRPC

让前后端共享类型的 TypeScript RPC 库,不需要写接口 schema

核心功能

tRPC 不是传统 Web 框架,而是把服务端 router 的类型直接导出给客户端使用,从而在不生成任何 schema、不做代码生成的前提下实现端到端类型安全。适合前后端同仓、全 TypeScript 的项目。

功能亮点

类型自动流到客户端

createTRPCClient<AppRouter>() 后调用 trpc.userById.query('1'),参数与返回值类型直接推断出来

省掉一层接口契约

不需要写 OpenAPI/GraphQL schema,也不需要代码生成步骤,类型就是唯一契约

查询与变更语义分明

query 走 HTTP GET 用于读取,mutation 走 HTTP POST 用于产生副作用的操作

校验库自由选择

.input() 接受任意解析器,zod、yup、valibot 均可,校验后的类型会带进 resolver

请求自动合批

httpBatchLink 把多次调用合并为一个 HTTP 请求,减少往返次数

适用场景

• 前后端同仓的 TypeScript 全栈项目,希望接口改动立刻在客户端报类型错误
• Next.js 应用的内部数据接口层,替代手写 fetch 封装与响应类型声明
• 小团队快速迭代的内部系统,不想为接口再维护一份 schema 或生成代码

安装配置

bash
环境要求:TypeScript >= 5.7.2;官方强烈建议 tsconfig.json 中开启 "strict": true,非 strict 模式不在官方支持范围内。

安装服务端与客户端包:
npm install @trpc/server @trpc/client

官方推荐把 tRPC 初始化、router 定义和服务器启动拆到不同文件,避免循环依赖:
.
├── server/
│   ├── trpc.ts        # tRPC 初始化
│   ├── appRouter.ts   # 接口逻辑与类型导出
│   └── index.ts       # HTTP 服务器
└── client/
    └── index.ts       # tRPC 客户端

使用方法

typescript
server/trpc.ts —— 初始化(每个后端只做一次):
import { initTRPC } from '@trpc/server';

const t = initTRPC.create();

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

server/appRouter.ts —— 定义接口并导出类型:
import { publicProcedure, router } from './trpc';
import { z } from 'zod';

export const appRouter = router({
  userList: publicProcedure.query(async () => {
    const users: User[] = [{ id: '1', name: 'Katt' }];
    return users;
  }),
  userById: publicProcedure.input(z.string()).query(async (opts) => {
    const { input } = opts;
    const user: User = { id: input, name: 'Katt' };
    return user;
  }),
});

export type AppRouter = typeof appRouter;

server/index.ts —— 用 standalone 适配器提供服务:
import { createHTTPServer } from '@trpc/server/adapters/standalone';
import { appRouter } from './appRouter';

const server = createHTTPServer({
  router: appRouter,
});

server.listen(3000);

client/index.ts —— 客户端调用:
import { createTRPCClient, httpBatchLink } from '@trpc/client';
import type { AppRouter } from './appRouter';

const trpc = createTRPCClient<AppRouter>({
  links: [httpBatchLink({ url: 'http://localhost:3000' })],
});

const user = await trpc.userById.query('1');
const createdUser = await trpc.userCreate.mutate({ name: 'Katt' });

关键指标

尚未核验对标产品,此处只列本工具自身指标,不做对比结论。

指标tRPC
价格免费
开源
上手难度进阶

相关工具

同类工具

优点

  • 服务端 router 类型经 type-only 导入直达客户端,接口签名改了客户端立即编译报错
  • 不需要 schema 文件也不需要代码生成步骤,类型定义本身就是接口契约
  • 输入校验器可自由选择 zod、yup、valibot,校验后的类型会自动带入 resolver 参数
  • httpBatchLink 自动把多次调用合并成一个 HTTP 请求,减少网络往返

缺点

  • 只适用于前后端都是 TypeScript 且能共享类型的场景,跨语言或对外开放的公开 API 用不上它的核心优势
  • 要求 TypeScript >= 5.7.2,且官方不支持非 strict 模式,老项目需要先调整 tsconfig
  • 自身不提供 HTTP 服务器,必须搭配 standalone、Express、Fastify 等适配器才能对外提供服务