Aller au contenu principal
Version : 11.x

Démarrage rapide

Traduction Bêta Non Officielle

Cette page a été traduite par PageTurner AI (bêta). Non approuvée officiellement par le projet. Vous avez trouvé une erreur ? Signaler un problème →

tRPC combine des concepts de REST et GraphQL. Si vous n'êtes familier avec aucun des deux, consultez les Concepts clés.

Installation

tRPC est réparti entre plusieurs packages, vous pouvez donc n'installer que ce dont vous avez besoin. Installez les packages dans les sections appropriées de votre base de code. Pour ce guide rapide, nous resterons simples en utilisant uniquement le client vanilla. Pour les frameworks, consultez l'utilisation avec React et l'utilisation avec Next.js.

Prérequis
  • tRPC nécessite TypeScript >=5.7.2
  • Nous recommandons fortement d'utiliser "strict": true dans votre tsconfig.json car nous ne prenons pas officiellement en charge le mode non-strict.

Commencez par installer les packages @trpc/server et @trpc/client :

npm install @trpc/server @trpc/client

Définition d'un routeur backend

Parcourons les étapes de création d'une API typée avec tRPC. Pour commencer, cette API contiendra trois endpoints avec ces signatures 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;

1. Créer une instance de routeur

D'abord, initialisons le backend tRPC. Il est recommandé de le faire dans un fichier séparé et d'exporter des fonctions d'aide réutilisables plutôt que l'objet tRPC complet.

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;

Ensuite, initialisons notre instance de routeur principale, souvent appelée appRouter, à laquelle nous ajouterons ultérieurement des procédures. Enfin, exportons le type du routeur que nous utiliserons côté client.

server/index.ts
ts
import { router } from './trpc';
 
const appRouter = router({
// ...
});
 
// Export type router type signature,
// NOT the router itself.
export type AppRouter = typeof appRouter;
server/index.ts
ts
import { router } from './trpc';
 
const appRouter = router({
// ...
});
 
// Export type router type signature,
// NOT the router itself.
export type AppRouter = typeof appRouter;

2. Ajouter une procédure de requête

Utilisez publicProcedure.query() pour ajouter une procédure de requête au routeur.

Ce qui suit crée une procédure de requête appelée userList qui renvoie une liste d'utilisateurs depuis notre base de données :

server/index.ts
ts
import { db } from './db';
import { publicProcedure, router } from './trpc';
 
const appRouter = router({
userList: publicProcedure
.query(async () => {
// Retrieve users from a datasource, this is an imaginary database
const users = await db.user.findMany();
const users: User[]
return users;
}),
});
server/index.ts
ts
import { db } from './db';
import { publicProcedure, router } from './trpc';
 
const appRouter = router({
userList: publicProcedure
.query(async () => {
// Retrieve users from a datasource, this is an imaginary database
const users = await db.user.findMany();
const users: User[]
return users;
}),
});

3. Utiliser un parseur d'entrée pour valider les inputs

Pour implémenter la procédure userById, nous devons accepter une entrée client. tRPC permet de définir des parseurs d'entrée pour valider et parser l'input. Vous pouvez définir votre propre parseur ou utiliser une bibliothèque de validation comme zod, yup ou superstruct.

Vous définissez votre parseur d'entrée dans publicProcedure.input(), accessible ensuite dans la fonction de résolution comme ci-dessous :

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



server.ts
ts
import { z } from 'zod';
 
const appRouter = router({
// ...
userById: publicProcedure
.input(z.string())
.query(async (opts) => {
const { input } = opts;
const input: string
// Retrieve the user with the given ID
const user = await db.user.findById(input);
const user: User | undefined
return user;
}),
});
server.ts
ts
import { z } from 'zod';
 
const appRouter = router({
// ...
userById: publicProcedure
.input(z.string())
.query(async (opts) => {
const { input } = opts;
const input: string
// Retrieve the user with the given ID
const user = await db.user.findById(input);
const user: User | undefined
return user;
}),
});
info

Dans le reste de cette documentation, nous utiliserons zod comme bibliothèque de validation.

4. Ajouter une procédure de mutation

Comme GraphQL, tRPC distingue les procédures de requête et de mutation.

Le fonctionnement d'une procédure côté serveur diffère peu entre requête et mutation. Le nom de la méthode change, et l'utilisation côté client diffère - mais tout le reste est identique !

Ajoutons une mutation userCreate en la définissant comme nouvelle propriété de notre objet routeur :

server.ts
ts
const appRouter = router({
// ...
userCreate: publicProcedure
.input(z.object({ name: z.string() }))
.mutation(async (opts) => {
const { input } = opts;
const input: { name: string; }
// Create a new user in the database
const user = await db.user.create(input);
const user: { name: string; id: string; }
return user;
}),
});
server.ts
ts
const appRouter = router({
// ...
userCreate: publicProcedure
.input(z.object({ name: z.string() }))
.mutation(async (opts) => {
const { input } = opts;
const input: { name: string; }
// Create a new user in the database
const user = await db.user.create(input);
const user: { name: string; id: string; }
return user;
}),
});

Exposition de l'API

Maintenant que notre routeur est défini, nous pouvons l'exposer. tRPC propose de nombreux adaptateurs pour utiliser le framework backend de votre choix. Pour rester simple, nous utiliserons l'adaptateur standalone.

server/index.ts
ts
import { createHTTPServer } from '@trpc/server/adapters/standalone';
 
const appRouter = router({
// ...
});
 
const server = createHTTPServer({
router: appRouter,
});
 
server.listen(3000);
server/index.ts
ts
import { createHTTPServer } from '@trpc/server/adapters/standalone';
 
const appRouter = router({
// ...
});
 
const server = createHTTPServer({
router: appRouter,
});
 
server.listen(3000);
See the full backend code
server/db.ts
ts
type User = { id: string; name: string };
 
// Imaginary database
const users: User[] = [];
export const db = {
user: {
findMany: async () => users,
findById: async (id: string) => users.find((user) => user.id === id),
create: async (data: { name: string }) => {
const user = { id: String(users.length + 1), ...data };
users.push(user);
return user;
},
},
};
server/db.ts
ts
type User = { id: string; name: string };
 
// Imaginary database
const users: User[] = [];
export const db = {
user: {
findMany: async () => users,
findById: async (id: string) => users.find((user) => user.id === id),
create: async (data: { name: string }) => {
const user = { id: String(users.length + 1), ...data };
users.push(user);
return user;
},
},
};

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/index.ts
ts
import { createHTTPServer } from "@trpc/server/adapters/standalone";
import { z } from "zod";
import { db } from "./db";
import { publicProcedure, router } from "./trpc";
 
const appRouter = router({
userList: publicProcedure
.query(async () => {
const users = await db.user.findMany();
return users;
}),
userById: publicProcedure
.input(z.string())
.query(async (opts) => {
const { input } = opts;
const user = await db.user.findById(input);
return user;
}),
userCreate: publicProcedure
.input(z.object({ name: z.string() }))
.mutation(async (opts) => {
const { input } = opts;
const user = await db.user.create(input);
return user;
}),
});
 
export type AppRouter = typeof appRouter;
 
const server = createHTTPServer({
router: appRouter,
});
 
server.listen(3000);
server/index.ts
ts
import { createHTTPServer } from "@trpc/server/adapters/standalone";
import { z } from "zod";
import { db } from "./db";
import { publicProcedure, router } from "./trpc";
 
const appRouter = router({
userList: publicProcedure
.query(async () => {
const users = await db.user.findMany();
return users;
}),
userById: publicProcedure
.input(z.string())
.query(async (opts) => {
const { input } = opts;
const user = await db.user.findById(input);
return user;
}),
userCreate: publicProcedure
.input(z.object({ name: z.string() }))
.mutation(async (opts) => {
const { input } = opts;
const user = await db.user.create(input);
return user;
}),
});
 
export type AppRouter = typeof appRouter;
 
const server = createHTTPServer({
router: appRouter,
});
 
server.listen(3000);

Utiliser votre nouveau backend côté client

Passons maintenant au code côté client pour découvrir la puissance de la sécurité des types de bout en bout. Lorsque nous importons le type AppRouter pour l'utiliser côté client, nous obtenons une sécurité typage complète pour notre système sans divulguer aucun détail d'implémentation au client.

1. Configurer le client tRPC

client/index.ts
ts
import { createTRPCClient, httpBatchLink } from '@trpc/client';
import type { AppRouter } from './server';
// 👆 **type-only** import
 
// Pass AppRouter as generic here. 👇 This lets the `trpc` object 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 './server';
// 👆 **type-only** import
 
// Pass AppRouter as generic here. 👇 This lets the `trpc` object know
// what procedures are available on the server and their input/output types.
const trpc = createTRPCClient<AppRouter>({
links: [
httpBatchLink({
url: 'http://localhost:3000',
}),
],
});

Les liens dans tRPC sont similaires aux liens dans GraphQL : ils nous permettent de contrôler le flux de données avant leur envoi au serveur. Dans l'exemple ci-dessus, nous utilisons le httpBatchLink, qui regroupe automatiquement plusieurs appels en une seule requête HTTP. Pour une utilisation plus approfondie des liens, consultez la documentation sur les liens.

2. Interrogation et mutation

Vous avez maintenant accès à vos procédures API via l'objet trpc. Essayez !

client/index.ts
ts
// Inferred types
const user = await trpc.userById.query('1');
const user: { name: string; id: string; } | undefined
 
const createdUser = await trpc.userCreate.mutate({ name: 'sachinraja' });
const createdUser: { name: string; id: string; }
client/index.ts
ts
// Inferred types
const user = await trpc.userById.query('1');
const user: { name: string; id: string; } | undefined
 
const createdUser = await trpc.userCreate.mutate({ name: 'sachinraja' });
const createdUser: { name: string; id: string; }

Autocomplétion complète

Ouvrez votre Intellisense pour explorer votre API côté frontend. Vous y trouverez toutes vos routes de procédures accompagnées des méthodes pour les appeler.

client/index.ts
ts
// Full autocompletion on your routes
trpc.u;
      
client/index.ts
ts
// Full autocompletion on your routes
trpc.u;
      

Essayez par vous-même !

Prochaines étapes

astuce

Nous vous encourageons vivement à explorer les exemples d'applications pour comprendre comment tRPC s'intègre dans votre framework préféré.

astuce

Par défaut, tRPC transforme les types complexes comme Date en leur équivalent JSON (soit string pour Date). Pour conserver l'intégrité de ces types, la méthode la plus simple est d'utiliser superjson comme Data Transformer.

tRPC inclut des outils côté client plus sophistiqués conçus pour les projets React et Next.js.