Saltar al contenido principal
Versión: 11.x

Inicio rápido

Traducción Beta No Oficial

Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →

Instalación

tRPC está dividido en varios paquetes, así que puedes instalar solo lo que necesites. Asegúrate de instalar los paquetes en las secciones adecuadas de tu códigobase. Para esta guía de inicio rápido, lo mantendremos simple y usaremos solo el cliente vanilla. Para guías de frameworks, consulta uso con React y uso con Next.js.

Requisitos
  • tRPC requiere TypeScript >=5.7.2
  • Recomendamos encarecidamente usar "strict": true en tu tsconfig.json ya que no admitimos oficialmente el modo no estricto.

Comienza instalando los paquetes @trpc/server y @trpc/client:

npm install @trpc/server @trpc/client
Agentes de IA

Si utilizas un agente de programación con IA, instala habilidades de tRPC para mejorar la generación de código:

bash
npx @tanstack/intent@latest install
bash
npx @tanstack/intent@latest install

Tu primera API con tRPC

Exploraremos los pasos para construir una API con seguridad de tipos usando tRPC. Inicialmente, esta API contendrá tres endpoints con estas firmas de TypeScript:

ts
type User = { id: string; name: string; };
userList: () => User[];
userById: (id: string) => User;
userCreate: (data: { name: string }) => User;
ts
type User = { id: string; name: string; };
userList: () => User[];
userById: (id: string) => User;
userCreate: (data: { name: string }) => User;

Esta es la estructura de archivos que construiremos. Recomendamos separar la inicialización de tRPC, la definición del router y la configuración del servidor en archivos distintos para evitar dependencias cíclicas:

.
├── server/
│ ├── trpc.ts # tRPC instantiation & setup
│ ├── appRouter.ts # Your API logic and type export
│ └── index.ts # HTTP server
└── client/
└── index.ts # tRPC client
.
├── server/
│ ├── trpc.ts # tRPC instantiation & setup
│ ├── appRouter.ts # Your API logic and type export
│ └── index.ts # HTTP server
└── client/
└── index.ts # tRPC client

1. Crear una instancia de enrutador

Primero, inicialicemos el backend de tRPC. Es una buena convención hacer esto en un archivo separado y exportar funciones auxiliares reutilizables en lugar del objeto tRPC completo.

server/trpc.ts
ts
import { initTRPC } from '@trpc/server';
 
/**
* Initialization of tRPC backend
* Should be done only once per backend!
*/
const t = initTRPC.create();
 
/**
* Export reusable router and procedure helpers
* that can be used throughout the router
*/
export const router = t.router;
export const publicProcedure = t.procedure;
server/trpc.ts
ts
import { initTRPC } from '@trpc/server';
 
/**
* Initialization of tRPC backend
* Should be done only once per backend!
*/
const t = initTRPC.create();
 
/**
* Export reusable router and procedure helpers
* that can be used throughout the router
*/
export const router = t.router;
export const publicProcedure = t.procedure;

A continuación, inicializaremos nuestra instancia principal del router, comúnmente llamada appRouter, a la que luego añadiremos procedimientos. Finalmente, necesitamos exportar el tipo del router que usaremos más tarde en el lado del cliente.

server/appRouter.ts
ts
import { router } from './trpc';
 
export const appRouter = router({
// ...
});
 
export type AppRouter = typeof appRouter;
server/appRouter.ts
ts
import { router } from './trpc';
 
export const appRouter = router({
// ...
});
 
export type AppRouter = typeof appRouter;

2. Añadir un procedimiento de consulta

Usa publicProcedure.query() para añadir un procedimiento de consulta al enrutador.

Lo siguiente crea un procedimiento de query llamado userList que devuelve una lista de usuarios:

server/appRouter.ts
ts
import { publicProcedure, router } from './trpc';
 
export const appRouter = router({
userList: publicProcedure
.query(async () => {
const users: User[] = [{ id: '1', name: 'Katt' }];
 
return users;
}),
});
 
export type AppRouter = typeof appRouter;
server/appRouter.ts
ts
import { publicProcedure, router } from './trpc';
 
export const appRouter = router({
userList: publicProcedure
.query(async () => {
const users: User[] = [{ id: '1', name: 'Katt' }];
 
return users;
}),
});
 
export type AppRouter = typeof appRouter;

3. Usar un analizador de entrada para validar inputs

Para implementar el procedimiento userById, necesitamos aceptar entrada del cliente. tRPC te permite definir analizadores de entrada para validar y procesar la entrada. Puedes definir tu propio analizador o usar una biblioteca de validación de tu elección, como zod, yup o superstruct.

Defines tu analizador de entrada en publicProcedure.input(), que luego se puede acceder en la función resolutora como se muestra a continuación:

The input parser can be any ZodType, e.g. z.string() or z.object().


server/appRouter.ts
ts
import { publicProcedure, router } from './trpc';
import { z } from 'zod';
 
export const appRouter = router({
// ...
userById: publicProcedure
.input(z.string())
.query(async (opts) => {
const { input } = opts;
const input: string
const user: User = { id: input, name: 'Katt' };
 
return user;
}),
});
 
export type AppRouter = typeof appRouter;
server/appRouter.ts
ts
import { publicProcedure, router } from './trpc';
import { z } from 'zod';
 
export const appRouter = router({
// ...
userById: publicProcedure
.input(z.string())
.query(async (opts) => {
const { input } = opts;
const input: string
const user: User = { id: input, name: 'Katt' };
 
return user;
}),
});
 
export type AppRouter = typeof appRouter;

4. Añadir un procedimiento de mutación

Similar a GraphQL, tRPC distingue entre procedimientos de Query y Mutation.

La distinción entre Query y Mutation es principalmente semántica. Las Queries usan HTTP GET y están destinadas a operaciones de lectura, mientras que las Mutations usan HTTP POST y están pensadas para operaciones que causan efectos secundarios.

Añadamos una mutación userCreate agregándola como nueva propiedad en nuestro objeto de enrutador:

server/appRouter.ts
ts
import { publicProcedure, router } from './trpc';
 
export const appRouter = router({
// ...
userCreate: publicProcedure
.input(z.object({ name: z.string() }))
.mutation(async (opts) => {
const { input } = opts;
const input: { name: string; }
// Create the user in your DB
const user: User = { id: '1', ...input };
 
return user;
}),
});
 
export type AppRouter = typeof appRouter;
server/appRouter.ts
ts
import { publicProcedure, router } from './trpc';
 
export const appRouter = router({
// ...
userCreate: publicProcedure
.input(z.object({ name: z.string() }))
.mutation(async (opts) => {
const { input } = opts;
const input: { name: string; }
// Create the user in your DB
const user: User = { id: '1', ...input };
 
return user;
}),
});
 
export type AppRouter = typeof appRouter;

Servir la API

Ahora que hemos definido nuestro router, podemos servirlo. tRPC tiene adaptadores de primera clase para muchos servidores web populares. Para mantenerlo simple, usaremos aquí el adaptador standalone para Node.js.

server/index.ts
ts
import { createHTTPServer } from '@trpc/server/adapters/standalone';
import { appRouter } from './appRouter';
 
const server = createHTTPServer({
router: appRouter,
});
 
server.listen(3000);
server/index.ts
ts
import { createHTTPServer } from '@trpc/server/adapters/standalone';
import { appRouter } from './appRouter';
 
const server = createHTTPServer({
router: appRouter,
});
 
server.listen(3000);
See the full backend code
server/trpc.ts
ts
import { initTRPC } from '@trpc/server';
 
const t = initTRPC.create();
 
export const router = t.router;
export const publicProcedure = t.procedure;
server/trpc.ts
ts
import { initTRPC } from '@trpc/server';
 
const t = initTRPC.create();
 
export const router = t.router;
export const publicProcedure = t.procedure;

server/appRouter.ts
ts
import { z } from "zod";
import { publicProcedure, router } from "./trpc";
 
type User = { id: string; name: string };
 
export const appRouter = router({
userList: publicProcedure
.query(async () => {
const users: User[] = [{ id: '1', name: 'Katt' }];
return users;
}),
userById: publicProcedure
.input(z.string())
.query(async (opts) => {
const { input } = opts;
const user: User = { id: input, name: 'Katt' };
return user;
}),
userCreate: publicProcedure
.input(z.object({ name: z.string() }))
.mutation(async (opts) => {
const { input } = opts;
const user: User = { id: '1', ...input };
return user;
}),
});
 
export type AppRouter = typeof appRouter;
server/appRouter.ts
ts
import { z } from "zod";
import { publicProcedure, router } from "./trpc";
 
type User = { id: string; name: string };
 
export const appRouter = router({
userList: publicProcedure
.query(async () => {
const users: User[] = [{ id: '1', name: 'Katt' }];
return users;
}),
userById: publicProcedure
.input(z.string())
.query(async (opts) => {
const { input } = opts;
const user: User = { id: input, name: 'Katt' };
return user;
}),
userCreate: publicProcedure
.input(z.object({ name: z.string() }))
.mutation(async (opts) => {
const { input } = opts;
const user: User = { id: '1', ...input };
return user;
}),
});
 
export type AppRouter = typeof appRouter;

server/index.ts
ts
import { createHTTPServer } from "@trpc/server/adapters/standalone";
import { appRouter } from "./appRouter";
 
const server = createHTTPServer({
router: appRouter,
});
 
server.listen(3000);
server/index.ts
ts
import { createHTTPServer } from "@trpc/server/adapters/standalone";
import { appRouter } from "./appRouter";
 
const server = createHTTPServer({
router: appRouter,
});
 
server.listen(3000);

Usar tu nuevo backend en el cliente

Ahora pasemos al código del lado del cliente y aprovechemos el poder de la seguridad de tipos de extremo a extremo. Cuando importamos el tipo AppRouter para que el cliente lo use, logramos una seguridad de tipos completa en nuestro sistema sin filtrar detalles de implementación al cliente.

1. Configurar el cliente de tRPC

client/index.ts
ts
import { createTRPCClient, httpBatchLink } from '@trpc/client';
import type { AppRouter } from './appRouter';
// 👆 **type-only** imports are stripped at build time
 
// Pass AppRouter as a type parameter. 👇 This lets `trpc` know
// what procedures are available on the server and their input/output types.
const trpc = createTRPCClient<AppRouter>({
links: [
httpBatchLink({
url: 'http://localhost:3000',
}),
],
});
client/index.ts
ts
import { createTRPCClient, httpBatchLink } from '@trpc/client';
import type { AppRouter } from './appRouter';
// 👆 **type-only** imports are stripped at build time
 
// Pass AppRouter as a type parameter. 👇 This lets `trpc` know
// what procedures are available on the server and their input/output types.
const trpc = createTRPCClient<AppRouter>({
links: [
httpBatchLink({
url: 'http://localhost:3000',
}),
],
});

Los links en tRPC son similares a los links en GraphQL: nos permiten controlar el flujo de datos hacia el servidor. En el ejemplo anterior, usamos el httpBatchLink, que agrupa automáticamente múltiples llamadas en una sola solicitud HTTP. Para un uso más avanzado de links, consulta la documentación de links.

2. Inferencia de tipos y autocompletado

Ahora tienes acceso a tus procedimientos de API en el objeto trpc. ¡Pruébalo!

client/index.ts
ts
// Inferred types
const user = await trpc.userById.query('1');
const user: User
 
const createdUser = await trpc.userCreate.mutate({ name: 'Katt' });
const createdUser: User
client/index.ts
ts
// Inferred types
const user = await trpc.userById.query('1');
const user: User
 
const createdUser = await trpc.userCreate.mutate({ name: 'Katt' });
const createdUser: User

También puedes usar tu autocompletado para explorar la API desde tu cliente

client/index.ts
ts
trpc.u;
      
 
 
client/index.ts
ts
trpc.u;
      
 
 

Próximos pasos

What's next?Description
Example AppsExplore tRPC in your chosen framework
TanStack React QueryRecommended React integration via @trpc/tanstack-react-query
Next.jsUsage with Next.js
Server AdaptersExpress, Fastify, and more
TransformersUse superjson to retain complex types like Date