Validation des données avec Zod

Utilise Zod pour typer et sécuriser les réponses de l’API.

4 min read

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 :

Terminal
1
npm 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 :

app/server/movies.ts
1
import { z } from 'zod'
2
3
const GetMoviesSchema = z.object({ // ^? z.object: crée un schema objet
4
page: z.number(), // ^? z.number: nombre de page
5
results: z.array(
6
z.object({
7
id: z.number(), // ^? z.number: identifiant du film
8
title: z.string(), // ^? z.string: titre du film
9
poster_path: z.string(), // ^? z.string: chemin de l'affiche
10
release_date: z.string(), // ^? z.string: date de sortie
11
})
12
),
13
})

Parser les données et renvoyer des résultats typés

Ensuite, utilise parse() pour valider la réponse brute et extraire results :

app/server/movies.ts
1
export async function getMovies() {
2
const data = await fetchMovieDb({ url: '/movie/popular' })
3
// @callout: parse l'objet `data` selon le schéma et lève si invalidé
4
const { results } = GetMoviesSchema.parse(data)
5
return results
6
}

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 :

app/server/movies.ts
1
export type Movie = z.infer<
2
typeof GetMoviesSchema
3
>['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 :

app/server/movies.ts
1
const GetSeriesSchema = z.object({
2
page: z.number(),
3
results: z.array(
4
z.object({
5
id: z.number(),
6
name: z.string(),
7
poster_path: z.string(),
8
first_air_date: z.string(),
9
})
10
),
11
})
12
13
export async function getSeries() {
14
const data = await fetchMovieDb({ url: '/tv/popular' })
15
const { results } = GetSeriesSchema.parse(data)
16
return results
17
}
18
19
export type Series = z.infer<
20
typeof GetSeriesSchema
21
>['results'][number]

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 :

app/server/movies.ts
1
// film détaillé
2
const GetMovieDetailSchema = z.object({
3
id: z.number(),
4
title: z.string(),
5
poster_path: z.string(),
6
release_date: z.string(),
7
})
8
9
export async function getMovie({ movieId }: { movieId: number }) {
10
'use cache'
11
const data = await fetchMovieDb({ url: `/movie/${movieId}` })
12
const result = GetMovieDetailSchema.parse(data) // lève si champs manquant
13
return result
14
}

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 objet success/error si tu veux gérer les erreurs sans exception.
  • Factorise tes schémas si plusieurs appels partagent des champs communs.

Exercices rapides

  1. Créer un schéma de détail de série
    Réalise un GetSerieDetailSchema dans app/server/movies.ts et valide la réponse de /tv/{serieId}.

  2. Tester la validation côté serveur
    Modifie getMovies() pour utiliser safeParse(). En cas d’erreur, logue le détail avant de rethrow.

  3. Étendre le type Movie
    Ajoute la propriété overview: z.string() dans GetMoviesSchema et vérifie que l’IDE remonte bien le type dans MovieCard.


Tu as maintenant toutes les clés pour sécuriser tes données externes et tirer pleinement parti de TypeScript !