Use Cases

tRPC API:Claude Code 实战指南

了解trpc api:Claude Code 实战. 包含实用技巧和代码示例。

tRPCで类型安全なAPI开发を実現する

tRPCは服务器と客户端間の类型を自動共有する框架です。Claude Code tRPCのルーター设计からプロシージャの实现まで、类型安全な结构を一貫して生成してくれます。

基本的ルーター结构

让 Claude Codeルーターの结构を依頼吧。

> tRPCのルーターを设计して。
> 用户CRUD、认证中间件、输入验证付きで。
import { initTRPC, TRPCError } from "@trpc/server";
import { z } from "zod";

type Context = {
  session: { userId: string; role: string } | null;
  db: PrismaClient;
};

const t = initTRPC.context<Context>().create();

// 中间件
const isAuthenticated = t.middleware(({ ctx, next }) => {
  if (!ctx.session) {
    throw new TRPCError({ code: "UNAUTHORIZED" });
  }
  return next({ ctx: { ...ctx, session: ctx.session } });
});

const protectedProcedure = t.procedure.use(isAuthenticated);

// 用户ルーター
export const userRouter = t.router({
  list: protectedProcedure
    .input(
      z.object({
        page: z.number().int().positive().default(1),
        perPage: z.number().int().min(1).max(100).default(20),
        search: z.string().optional(),
      })
    )
    .query(async ({ ctx, input }) => {
      const { page, perPage, search } = input;
      const where = search
        ? { name: { contains: search, mode: "insensitive" as const } }
        : {};

      const [users, total] = await Promise.all([
        ctx.db.user.findMany({
          where,
          skip: (page - 1) * perPage,
          take: perPage,
          orderBy: { createdAt: "desc" },
        }),
        ctx.db.user.count({ where }),
      ]);

      return { users, total, totalPages: Math.ceil(total / perPage) };
    }),

  getById: protectedProcedure
    .input(z.object({ id: z.string().uuid() }))
    .query(async ({ ctx, input }) => {
      const user = await ctx.db.user.findUnique({
        where: { id: input.id },
      });
      if (!user) throw new TRPCError({ code: "NOT_FOUND" });
      return user;
    }),

  create: protectedProcedure
    .input(
      z.object({
        name: z.string().min(2).max(50),
        email: z.string().email(),
        role: z.enum(["admin", "editor", "viewer"]),
      })
    )
    .mutation(async ({ ctx, input }) => {
      return ctx.db.user.create({ data: input });
    }),

  update: protectedProcedure
    .input(
      z.object({
        id: z.string().uuid(),
        name: z.string().min(2).max(50).optional(),
        email: z.string().email().optional(),
        role: z.enum(["admin", "editor", "viewer"]).optional(),
      })
    )
    .mutation(async ({ ctx, input }) => {
      const { id, ...data } = input;
      return ctx.db.user.update({ where: { id }, data });
    }),
});

客户端側の类型安全な呼び出し

tRPCの最大の利点は、客户端側で服务器の类型が那个まま使えることです。

import { createTRPCReact } from "@trpc/react-query";
import type { AppRouter } from "../server/router";

export const trpc = createTRPCReact<AppRouter>();

function UserList() {
  const { data, isLoading } = trpc.user.list.useQuery({
    page: 1,
    perPage: 20,
  });

  const createUser = trpc.user.create.useMutation({
    onSuccess: () => {
      utils.user.list.invalidate();
    },
  });

  const utils = trpc.useUtils();

  if (isLoading) return <div>読み込み中...</div>;

  return (
    <div>
      {data?.users.map((user) => (
        <div key={user.id}>
          <span>{user.name}</span>
          <span>{user.email}</span>
        </div>
      ))}
    </div>
  );
}

错误处理の设计

让 Claude Code错误处理の仕組みも设计してもらいましょう。

import { TRPCError } from "@trpc/server";

// カスタム错误格式化工具
const t = initTRPC.context<Context>().create({
  errorFormatter({ shape, error }) {
    return {
      ...shape,
      data: {
        ...shape.data,
        zodError:
          error.cause instanceof ZodError ? error.cause.flatten() : null,
      },
    };
  },
});

// 错误をキャッチする中间件
const errorHandler = t.middleware(async ({ next }) => {
  try {
    return await next();
  } catch (error) {
    if (error instanceof TRPCError) throw error;

    console.error("Unexpected error:", error);
    throw new TRPCError({
      code: "INTERNAL_SERVER_ERROR",
      message: "予期せぬエラーが発生しました",
    });
  }
});

サブスクリプション(实时通信)

WebSocket経由の实时通信もtRPCで类型安全に实现可以。

import { observable } from "@trpc/server/observable";

export const notificationRouter = t.router({
  onNew: protectedProcedure.subscription(({ ctx }) => {
    return observable<Notification>((emit) => {
      const handler = (notification: Notification) => {
        if (notification.userId === ctx.session.userId) {
          emit.next(notification);
        }
      };

      eventEmitter.on("notification", handler);
      return () => eventEmitter.off("notification", handler);
    });
  }),
});

总结

tRPCとClaude Codeの組み合わせは、类型安全な全栈开发を最速で実現する手段です。Zod通过输入验证との集成で、ランタイムの安全性も同時に確保可以。

输入验证的详细信息请参阅Zod验证実践指南を、客户端側の数据获取はTanStack Query活用指南tRPC官方文档も併せて确认吧。

#Claude Code #tRPC #TypeScript #API #type safety