Presentando tRPC
Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →
tRPC te ofrece seguridad de tipos de extremo a extremo desde tu servidor (node) hasta tu cliente, sin siquiera declarar tipos. Todo lo que haces en el backend es devolver datos en una función, y en el frontend usas esos datos según el nombre del endpoint.
👋 Soy Alex, o "KATT" en GitHub, y quiero hablarte de una biblioteca llamada tRPC. Aún no he publicado artículos sobre ella, así que escribo esta introducción para empezar (pero ya hemos alcanzado >530 🌟 en GitHub). ¡Espera artículos y videos introductorios! Si quieres mantenerte actualizado o hacer preguntas, sígueme en Twitter @alexdotjs.
Así se ve al hacer un endpoint tRPC y una llamada desde el cliente:

He creado una biblioteca para React (@trpc/react) que se apoya en la excelente react-query, pero la biblioteca cliente (@trpc/client) funciona sin React (si quieres crear una lib específica para Svelte/Vue/Angular/[..], ¡contáctame!).
No hay generación de código involucrada y puedes agregarlo fácilmente a tu proyecto existente de Next.js/CRA/Express.
Ejemplo
Aquí un ejemplo de un procedimiento tRPC (también llamado endpoint) llamado hello que recibe un argumento string.
tsxconst appRouter = trpc.router().query('hello', {input: z.string().optional(),resolve: ({ input }) => {return {text: `hello ${input ?? 'world'}`,};},});export type AppRouter = typeof appRouter;
tsxconst appRouter = trpc.router().query('hello', {input: z.string().optional(),resolve: ({ input }) => {return {text: `hello ${input ?? 'world'}`,};},});export type AppRouter = typeof appRouter;
Y así se ve un cliente con seguridad de tipos usando esos datos:
tsximport type { AppRouter } from './server';async function main() {const client = createTRPCClient<AppRouter>({url: `http://localhost:2022`,});const result = await client.query('hello', '@alexdotjs');console.log(result); // --> { text: "hello @alexdotjs" }}main();
tsximport type { AppRouter } from './server';async function main() {const client = createTRPCClient<AppRouter>({url: `http://localhost:2022`,});const result = await client.query('hello', '@alexdotjs');console.log(result); // --> { text: "hello @alexdotjs" }}main();
¡Eso es todo lo que necesitas para tener seguridad de tipos! El result infiere su tipo a partir de lo que devuelve el backend. Los datos de entrada también se infieren del validador, así que los datos son seguros para usar directamente; de hecho, debes pasar los datos de entrada por un validador (y tRPC funciona con zod/yup/validadores personalizados desde el primer momento).
Aquí un enlace de CodeSandbox para probar el ejemplo: https://githubbox.com/trpc/trpc/tree/main/examples/standalone-server (¡mira la salida del terminal en lugar de la vista previa!).
¿Qué? ¿Estoy importando código del backend al cliente? - No, en realidad no lo haces
Aunque parezca que sí, no se comparte código del servidor al cliente; el import type de TypeScript "[...] solo importa declaraciones para anotaciones de tipos. Siempre se elimina completamente, sin dejar rastro en tiempo de ejecución." - función añadida en TypeScript 3.8 - ver documentación.
No hay generación de código, puedes implementarlo hoy mismo siempre que tengas cómo compartir tipos entre servidor y cliente (ojalá ya uses un monorepo).
¡Pero solo estamos comenzando!
Mencioné antes que existe una biblioteca para React; para usar los datos anteriores en React harías:
tsxconst { data } = trpc.useQuery(['hello', '@alexdotjs']);
tsxconst { data } = trpc.useQuery(['hello', '@alexdotjs']);
... y obtendrás datos con seguridad de tipos en el cliente.
Puedes agregar tRPC hoy a tu proyecto existente (tiene adaptadores para Express/Next.js), funciona con CRA y debería funcionar con React Native. Ni siquiera está atado a React, así que si quieres crear una lib para Svelte o Vue, contáctame.
¿Qué hay sobre la mutación de datos?
Las mutaciones son tan simples como las consultas; en el fondo son iguales, pero se exponen diferente como azúcar sintáctico y generan peticiones HTTP POST en lugar de GET.
Aquí tienes un ejemplo un poco más complejo usando una base de datos, tomado de nuestro ejemplo TodoMVC en todomvc.trpc.io / https://github.com/trpc/trpc/tree/main/examples/next-prisma-todomvc
tsxconst todoRouter = createRouter().mutation('add', {input: z.object({id: z.string().uuid(),data: z.object({completed: z.boolean().optional(),text: z.string().min(1).optional(),}),}),async resolve({ ctx, input }) {const { id, data } = input;const todo = await ctx.task.update({where: { id },data,});return todo;},});
tsxconst todoRouter = createRouter().mutation('add', {input: z.object({id: z.string().uuid(),data: z.object({completed: z.boolean().optional(),text: z.string().min(1).optional(),}),}),async resolve({ ctx, input }) {const { id, data } = input;const todo = await ctx.task.update({where: { id },data,});return todo;},});
Y el uso con React se ve así:
tsxconst addTask = trpc.useMutation('todos.add');return (<><inputplaceholder="What needs to be done?"onKeyDown={(e) => {const text = e.currentTarget.value.trim();if (e.key === 'Enter' && text) {addTask.mutate({ text });e.currentTarget.value = '';}}}/></>)
tsxconst addTask = trpc.useMutation('todos.add');return (<><inputplaceholder="What needs to be done?"onKeyDown={(e) => {const text = e.currentTarget.value.trim();if (e.key === 'Enter' && text) {addTask.mutate({ text });e.currentTarget.value = '';}}}/></>)
Fin por ahora.
Como dije, solo quería empezar a rodar la bola. Hay muchas más cosas:
-
Crear contexto para solicitudes entrantes con datos específicos de usuario que se inyectan como dependencias en los resolvers - enlace
-
Soporte para middlewares en routers - enlace
-
Fusión de routers (probablemente no quieras todos tus datos backend en un solo archivo) - enlace
-
El renderizado del lado del servidor más simple que hayas visto en el ecosistema React usando nuestro adaptador
@trpc/next- enlace -
Formateo de errores con seguridad de tipos - enlace
-
Transformadores de datos (usa objetos Date/Map/Set a través del cable) - enlace
-
Utilidades para React Query
Si quieres comenzar, hay varios ejemplos en la Guía de inicio para Next.js.
