The Disconnect
In a traditional REST API workflow, you define your backend types, then you manually write Swagger docs, and then your frontend team (which might just be you) manually writes TypeScript interfaces that hopefully match the backend.
This duplication is the root of all evil. It introduces a boundary where bugs thrive. What if your frontend code could "import" your backend functions directly?
The Solution: tRPC
tRPC allows you to build end-to-end typesafe APIs without schemas or code generation. It leverages TypeScript's inference to share type definitions between your client and server automatically.
Code Example
Here is what it looks like to call a backend function from a React component with 100% type safety:
// server/routers/user.ts
export const userRouter = router({
getUser: publicProcedure
.input(z.object({ id: z.string() }))
.query(async ({ input, ctx }) => {
return await ctx.prisma.user.findUnique({
where: { id: input.id }
});
}),
});
// client/UserProfile.tsx
const UserProfile = ({ userId }) => {
// Autocomplete works here! 'data' is typed exactly as the User model.
const { data, isLoading } = trpc.user.getUser.useQuery({ id: userId });
if (isLoading) return <Spinner />;
return <div>{data?.name}</div>; // TypeScript protects you if 'name' doesn't exist
};
If you change the backend model effectively renaming name to fullName, your frontend build will fail immediately. No more runtime errors. Just pure, unadulterated typed bliss.

