
关于
使用 tRPC 构建端到端类型安全 API——路由器、过程、中间件、订阅和 Next.js/React 集成模式。
name: trpc-fullstack description: "使用 tRPC 构建端到端类型安全的 API——路由器、过程、中间件、订阅和 Next.js/React 集成模式。" category: framework risk: none source: community date_added: "2026-03-17" author: suhaibjanjua tags: [typescript, trpc, api, fullstack, nextjs, react, type-safety] tools: [claude, cursor, gemini]
tRPC 全栈
概述
tRPC 让你无需编写 schema 或代码生成步骤即可构建完全类型安全的 API。你的 TypeScript 类型从服务器路由器直接流向客户端——因此每个 API 调用都有自动补全、编译时验证,且重构安全。当构建 TypeScript monorepo、Next.js 应用或任何服务器和客户端共享代码库的项目时使用此技能。
何时使用此技能
- 当构建 TypeScript 全栈应用(Next.js、Remix、Express + React)且客户端和服务器共享单一仓库时
- 当你想要端到端类型安全的 API 调用而无需 REST/GraphQL schema 开销时
- 当向现有 tRPC 设置添加实时功能(订阅)时
- 当在 tRPC 过程上设计多步中间件(认证、限流、租户范围)时
- 当将现有 REST/GraphQL API 增量迁移到 tRPC 时
核心概念
路由器和过程
路由器将相关的过程分组(类似于:端点)。过程是类型化函数——query 用于读取,mutation 用于写入,subscription 用于实时流。
使用 Zod 进行输入验证
所有过程输入都使用 Zod schema 验证。验证后的类型化输入在过程处理器中可用——无需手动解析。
上下文
context 是传递给每个过程的共享状态——认证会话、数据库客户端、请求头等。它在上下文工厂中每个请求构建一次。重要: Next.js App Router 和 Pages Router 需要不同的上下文工厂,因为 App Router 处理器接收 fetch Request,而不是 Node.js NextApiRequest。
中间件
中间件链在过程之前运行。用于认证、日志记录和请求增强。它们可以为下游过程扩展上下文。
工作原理
步骤 1:安装和初始化
npm install @trpc/server @trpc/client @trpc/react-query @tanstack/react-query zod
创建 tRPC 实例和可复用的构建器:
// src/server/trpc.ts
import { initTRPC, TRPCError } from '@trpc/server';
import { type Context } from './context';
import { ZodError } from 'zod';
const t = initTRPC.context<Context>().create({
errorFormatter({ shape, error }) {
return {
...shape,
data: {
...shape.data,
zodError:
error.cause instanceof ZodError ? error.cause.flatten() : null,
},
};
},
});
export const router = t.router;
export const publicProcedure = t.procedure;
export const middleware = t.middleware;
步骤 2:定义两个上下文工厂
Next.js App Router 处理器接收 fetch Request(不是 Node.js NextApiRequest),因此上下文必须根据调用位置以不同方式构建。为每个表面定义一个工厂:
// src/server/context.ts
import { type FetchCreateContextFnOptions } from '@trpc/server/adapters/fetch';
import { auth } from '@/server/auth'; // Next-Auth v5 / 你的认证助手
import { db } from './db';
/**
* HTTP 处理器(App Router Route Handler)的上下文。
* `opts.req` 是 fetch Request——认证通过 `auth()` 在服务端解析。
*/
export async function createTRPCContext(opts: FetchCreateContextFnOptions) {
const session = await auth(); // 服务端认证——无需 req/res
return { session, db, headers: opts.req.headers };
}
/**
* 直接服务端调用者(Server Components、RSC、cron jobs)的上下文。
* 不涉及 HTTP 请求,因此直接从服务器调用 auth()。
*/
export async function createServerContext() {
const session = await auth();
return { session, db };
}
export type Context = Awaited<ReturnType<typeof createTRPCContext>>;
步骤 3:构建认证中间件和受保护过程
// src/server/trpc.ts (续)
const enforceAuth = middleware(({ ctx, next }) => {
if (!ctx.session?.user) {
throw new TRPCError({ code: 'UNAUTHORIZED' });
}
return next({
ctx: {
// 收窄类型:从这里开始 session 非空
session: { ...ctx.session, user: ctx.session.user },
},
});
});
export const protectedProcedure = t.procedure.use(enforceAuth);
步骤 4:创建路由器
// src/server/routers/post.ts
import { z } from 'zod';
import { router, publicProcedure, protectedProcedure } from '../trpc';
import { TRPCError } from '@trpc/server';
export const postRouter = router({
list: publicProcedure
.input(
z.object({
limit: z.number().min(1).max(100).default(20),
cursor: z.string().optional(),
})
)
.query(async ({ input, ctx }) => {
// 实现分页查询
}),
});
兼容工具
Claude CodeCursor
标签
后端开发
