Skip to content
Go back

Using tRPC for End-to-End Type Safety

Using tRPC for End-to-End Type Safety

Introduction

tRPC enables building type-safe APIs in TypeScript, sharing types between client and server without code generation.

Prerequisites

Step 1: Install Dependencies

pnpm add @trpc/server @trpc/client @trpc/react-query zod
pnpm add -D @types/node

Step 2: Define Router on Server

Create src/server/trpc.ts:

import { initTRPC } from '@trpc/server';
import { z } from 'zod';

const t = initTRPC.create();

export const appRouter = t.router({
  getUser: t.procedure
    .input(z.object({ id: z.string() }))
    .query(({ input }) => {
      // Fetch user from DB
      return { id: input.id, name: 'Alice' };
    }),

  createUser: t.procedure
    .input(z.object({ name: z.string().min(1) }))
    .mutation(({ input }) => {
      // Create user in DB
      return { id: '123', name: input.name };
    }),
});

// Export types
export type AppRouter = typeof appRouter;

Register endpoint in Express or Next.js API route:

import express from 'express';
import * as trpcExpress from '@trpc/server/adapters/express';
import { appRouter } from './trpc';

const app = express();

app.use(
  '/trpc',
  trpcExpress.createExpressMiddleware({
    router: appRouter,
    createContext: () => null,
  })
);

app.listen(4000, () => console.log('tRPC server running'));  

Step 3: Setup tRPC Client in React

Create src/utils/trpc.ts:

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

export const trpc = createTRPCReact<AppRouter>();

In App.tsx:

import React from 'react';
import { trpc } from './utils/trpc';

function App() {
  const utils = trpc.useContext();
  const { data } = trpc.getUser.useQuery({ id: '123' });
  
  const createUser = trpc.createUser.useMutation({
    onSuccess: () => utils.getUser.invalidate(),
  });

  return (
    <div>
      <h1>User: {data?.name}</h1>
      <button
        onClick={() => createUser.mutate({ name: 'Bob' })}
      >
        Create User
      </button>
    </div>
  );
}

export default App;

Step 4: Type Safety Advantage

Summary

tRPC provides end-to-end type safety by sharing TypeScript types directly between server and client, eliminating runtime errors and extensive code generation.


Share this post on:

Previous Post
Comparing pnpm, npm, and Yarn for Large Projects
Next Post
Integrating GitHub Actions with Docker Builds