Type Safety de extremo a extremo con tRPC y Prisma
Cómo conectar tRPC, Prisma y Zod para que un cambio en el esquema de BD aparezca como error de TypeScript antes de llegar a producción.
El hueco de type safety entre backend y frontend
Incluso en un monorepo TypeScript, la frontera de la API suele estar sin tipos. Escribís un endpoint REST que devuelve un objeto User, y en el cliente casteás la respuesta JSON a un tipo User esperando que se mantengan sincronizados. Nunca lo hacen.
tRPC cierra esta brecha generando las definiciones de tipos del cliente directamente desde el router del servidor. Sin paso de generación de código, sin archivo de schema separado — es solo inferencia de TypeScript.
Prisma como fuente de verdad de la base de datos
El archivo schema.prisma de Prisma se convierte en la definición autoritativa de tus datos. Correr prisma generate emite métodos de cliente completamente tipados — así que las queries a la base de datos devuelven objetos correctamente tipados, no any.
// server/routers/user.ts
import { z } from 'zod';
import { router, publicProcedure } from '../trpc';
import { prisma } from '../db';
export const userRouter = router({
byId: publicProcedure
.input(z.object({ id: z.string().cuid() }))
.query(({ input }) => prisma.user.findUnique({ where: { id: input.id } })),
});Zod para validación de inputs
Los schemas de Zod cumplen doble función: validan el input en runtime (para que los clientes no puedan enviar basura) e infieren tipos TypeScript para los objetos de input. Escribís el schema una vez y obtenés ambos beneficios.
La cascada cuando cambiás un schema
- Actualizás schema.prisma
- Corrés prisma migrate dev
- prisma generate actualiza los tipos del cliente Prisma
- Los procedimientos de tRPC que usan esos tipos se ponen rojos en TypeScript
- Arreglás los procedimientos — y los callers del cliente también se ponen rojos
- Arreglás el cliente — y terminaste, con confianza
Esa cascada es el punto central. El error de tipos es tu suite de tests. Cuando estás en verde, tocaste todas las capas que se ven afectadas por el cambio.
tRPC no es magia. Es solo inferencia de TypeScript aplicada consistentemente desde el schema de base de datos hasta la última línea de código del cliente. El resultado parece magia porque encontrar bugs a nivel de tipos es mucho más barato que encontrarlos en producción.