Validation des données avec Zod
Utilise Zod pour typer et sécuriser les réponses de l’API.
Accéder gratuitement à cette formation
Renseigne ton email pour débloquer immédiatement cette formation gratuite.
Dans cette leçon, tu vas apprendre à protéger tes données provenant de l’API The Movie Database en utilisant Zod. Plutôt que de travailler avec du any, Zod te permet de :
- Décrire un schéma pour les réponses de l’API
- Valider automatiquement les propriétés reçues
- Inférer des types TypeScript à partir du schéma
ℹ️ On se concentre ici sur la validation côté serveur dans
app/server/movies.ts.
Installer Zod
Démarre par ajouter Zod à ton projet :
1npm install zod
Définir le schéma pour une liste de films
Ouvre app/server/movies.ts et ajoute un schéma qui reflète la structure renvoyée par l’API :
1import { z } from 'zod'23const GetMoviesSchema = z.object({ // ^? z.object: crée un schema objet4page: z.number(), // ^? z.number: nombre de page5results: z.array(6z.object({7id: z.number(), // ^? z.number: identifiant du film8title: z.string(), // ^? z.string: titre du film9poster_path: z.string(), // ^? z.string: chemin de l'affiche10release_date: z.string(), // ^? z.string: date de sortie11})12),13})
Pourquoi ce schéma ?
On décrit ici exactement ce qu’on attend de l’API. Si la réponse ne correspond pas,
GetMoviesSchema.parse()lève une exception, ce qui évite des bugs silencieux.
Parser les données et renvoyer des résultats typés
Ensuite, utilise parse() pour valider la réponse brute et extraire results :
1export async function getMovies() {2const data = await fetchMovieDb({ url: '/movie/popular' })3// @callout: parse l'objet `data` selon le schéma et lève si invalidé4const { results } = GetMoviesSchema.parse(data)5return results6}
Une fois validées, les données sont considérées « sûres ». Tu peux boucler dessus sans crainte.
Inférer le type Movie
Pour bénéficier de la complétion TypeScript, crée un type à partir du schéma :
1export type Movie = z.infer<2typeof GetMoviesSchema3>['results'][number] // ^? infère le type d'un élément du tableau results
Désormais, getMovies() renvoie un Movie[] et chaque movie est typé précisément.
Étendre la validation aux séries
L’API propose également /tv/popular. Tu peux définir un schéma similaire :
1const GetSeriesSchema = z.object({2page: z.number(),3results: z.array(4z.object({5id: z.number(),6name: z.string(),7poster_path: z.string(),8first_air_date: z.string(),9})10),11})1213export async function getSeries() {14const data = await fetchMovieDb({ url: '/tv/popular' })15const { results } = GetSeriesSchema.parse(data)16return results17}1819export type Series = z.infer<20typeof GetSeriesSchema21>['results'][number]
Tip
Toujours créer un schéma distinct si la forme des données change (ex.
namevstitle).
Validation d’un film ou d’une série détaillée
Pour l’appel /movie/{id} ou /tv/{id}, tu peux valider un objet unique :
1// film détaillé2const GetMovieDetailSchema = z.object({3id: z.number(),4title: z.string(),5poster_path: z.string(),6release_date: z.string(),7})89export async function getMovie({ movieId }: { movieId: number }) {10'use cache'11const data = await fetchMovieDb({ url: `/movie/${movieId}` })12const result = GetMovieDetailSchema.parse(data) // lève si champs manquant13return result14}
Tu peux faire de même pour getSerie().
Bonnes pratiques
- Toujours valider avant de manipuler les données.
- Utilise
safeParse()pour récupérer un objetsuccess/errorsi tu veux gérer les erreurs sans exception. - Factorise tes schémas si plusieurs appels partagent des champs communs.
Performance
Valider de gros objets peut être coûteux. Si tu appelles souvent le même endpoint,
cache le résultat ou utilise fetch avec use cache pour React Server Components.
Exercices rapides
-
Créer un schéma de détail de série
Réalise unGetSerieDetailSchemadansapp/server/movies.tset valide la réponse de/tv/{serieId}. -
Tester la validation côté serveur
ModifiegetMovies()pour utilisersafeParse(). En cas d’erreur, logue le détail avant de rethrow. -
Étendre le type
Movie
Ajoute la propriétéoverview: z.string()dansGetMoviesSchemaet vérifie que l’IDE remonte bien le type dansMovieCard.
Tu as maintenant toutes les clés pour sécuriser tes données externes et tirer pleinement parti de TypeScript !