DEV Community

Atlas Whoff
Atlas Whoff

Posted on

tRPC: End-to-End Type Safety Without REST or GraphQL

tRPC: End-to-End Type Safety Without REST or GraphQL

tRPC lets you call server functions from your client as if they were local functions — fully typed, no code generation, no schema files.

How It Works

Define procedures on the server:

import { z } from 'zod';
import { router, publicProcedure } from './trpc';

export const appRouter = router({
  users: router({
    list: publicProcedure
      .input(z.object({ limit: z.number().default(10) }))
      .query(async ({ input }) => db.users.findMany({ take: input.limit })),

    create: publicProcedure
      .input(z.object({ name: z.string(), email: z.string().email() }))
      .mutation(async ({ input }) => db.users.create({ data: input })),
  }),
});

export type AppRouter = typeof appRouter;
Enter fullscreen mode Exit fullscreen mode

Call them from the client with full autocomplete:

const { data: users } = trpc.users.list.useQuery({ limit: 20 });
const createUser = trpc.users.create.useMutation();
Enter fullscreen mode Exit fullscreen mode

No REST endpoints. No fetch calls. No any types. If the server changes the response shape, TypeScript errors immediately in the client.

Protected Procedures

const isAuthed = t.middleware(({ ctx, next }) => {
  if (!ctx.session) throw new TRPCError({ code: 'UNAUTHORIZED' });
  return next({ ctx: { session: ctx.session } });
});

export const protectedProcedure = t.procedure.use(isAuthed);
Enter fullscreen mode Exit fullscreen mode

When NOT to Use tRPC

tRPC requires both client and server to be TypeScript in the same monorepo. If external clients (mobile apps, third-party integrations) need to consume your API, use REST or GraphQL.

tRPC + Next.js + Prisma + NextAuth + Stripe — this exact stack is pre-wired in the AI SaaS Starter Kit. Skip the plumbing and start building.

Top comments (0)