Construire des clients API type-safe avec OpenAPI et TypeScript
Tous les développeurs frontend y ont été confrontés : vous récupérez des données depuis une API, accédez à un champ qui devrait exister, et obtenez undefined à l’exécution. TypeScript était censé empêcher cela. Le problème est que response.json() retourne any, donc le compilateur n’a rien à vérifier. Ce guide vous montre comment résoudre ce problème correctement—en générant les types directement depuis votre spécification OpenAPI et en les utilisant pour construire des clients REST type-safe en TypeScript.
Points clés à retenir
- Les interfaces TypeScript écrites manuellement dérivent de votre API réelle, créant un faux sentiment de sécurité qui conduit à des erreurs à l’exécution.
- La génération de code OpenAPI produit des types directement depuis votre spécification API, maintenant votre frontend et backend synchronisés.
- Utilisez
openapi-typescriptavecopenapi-fetchpour une configuration légère basée sur fetch, ou Orval pour des hooks TanStack Query générés et des SDK clients complets. - Automatisez la génération de types dans votre CI ou vos scripts de build pour que les types ne deviennent jamais obsolètes.
- Associez les types générés à un validateur d’exécution comme Zod pour les endpoints critiques où la sécurité à la compilation seule ne suffit pas.
Pourquoi le typage manuel échoue
La solution naïve consiste à écrire des interfaces à la main :
// ❌ Compile correctement, mais TypeScript vous fait simplement confiance
const data = (await response.json()) as User
Cela vous donne l’autocomplétion, mais cela devient un mensonge dès que le backend change. Vos types dérivent de la réalité, et vous revenez aux surprises à l’exécution.
La meilleure approche : générer les types depuis la source de vérité—votre spécification OpenAPI.
Le workflow de génération de code TypeScript OpenAPI
Le workflow typique ressemble à ceci :
- Partir d’une spécification OpenAPI (YAML ou JSON, hébergée ou locale)
- Exécuter un générateur pour produire des types TypeScript ou un client complet
- Importer ces types dans votre code applicatif
Cela maintient votre frontend synchronisé avec le backend automatiquement. Lorsque la spécification change, vous régénérez et TypeScript vous indique exactement ce qui a cassé.
Choisir votre approche : types uniquement vs SDK client complet
Il existe deux stratégies principales pour la génération de code TypeScript OpenAPI, et le bon choix dépend de votre projet.
| Approche | Outils | Idéal pour |
|---|---|---|
| Générer les types, apporter votre propre fetch | openapi-typescript + openapi-fetch | Projets légers basés sur fetch |
| Générer un SDK client complet | Orval, OpenAPI Generator | Équipes souhaitant des hooks et clients prêts à l’emploi |
La génération de types uniquement garde votre bundle léger et vous laisse contrôler la couche HTTP. La génération de SDK complet économise du temps de câblage mais ajoute plus de code généré à maintenir.
OpenAPI 3.0 vs 3.1 : La plupart des outils supportent bien OpenAPI 3.0. Le support d’OpenAPI 3.1 varie—vérifiez la documentation de votre générateur avant de supposer une compatibilité complète.
Discover how at OpenReplay.com.
Approche 1 : openapi-typescript avec openapi-fetch
C’est le chemin avec le runtime minimal. Générez les types depuis votre spécification, puis utilisez openapi-fetch comme une enveloppe mince et entièrement typée autour de l’API Fetch native.
npx openapi-typescript ./openapi.yaml -o ./src/api/types.ts
npm install openapi-fetch
import createClient from "openapi-fetch"
import type { paths } from "./api/types"
const client = createClient<paths>({ baseUrl: "https://api.example.com" })
// Le chemin, les paramètres et la réponse sont tous vérifiés par le typage
const { data, error } = await client.GET("/users/{id}", {
params: { path: { id: 123 } },
})
// TypeScript sait exactement à quoi ressemble `data`
console.log(data?.email)
Les fautes de frappe dans les chemins, les types de paramètres incorrects et les formes de réponse incompatibles deviennent tous des erreurs de compilation. Surcharge d’exécution minimale et seulement une petite dépendance runtime (openapi-fetch).
Approche 2 : Orval pour la génération de client complet
Orval génère des fonctions API typées et—de manière critique—peut produire des hooks TanStack Query directement depuis votre spécification. C’est utile lorsque vous voulez que la logique de récupération de données soit gérée pour vous.
npm install orval --save-dev
Configurez orval.config.ts pour pointer vers votre spécification et choisir un mode de sortie (fetch, axios ou react-query). Orval génère ensuite des fonctions comme useGetUsers() avec la sécurité de type intégrée.
Cette approche ajoute plus de code généré, mais pour les API plus grandes, elle réduit considérablement le code répétitif.
Maintenir les types synchronisés
La vraie valeur de la génération de client TypeScript OpenAPI ne tient que si vous régénérez de manière cohérente. Ajoutez l’étape de génération à votre workflow de développement :
{
"scripts": {
"generate:api": "openapi-typescript ./openapi.yaml -o ./src/api/types.ts"
}
}
Exécutez-le dans votre CI, ou surveillez les changements de spécification localement. Certaines équipes commitent le fichier généré ; d’autres régénèrent à chaque build. Les deux fonctionnent—rendez-le simplement automatique.
Ce que vous devez encore gérer
Les types générés fournissent généralement uniquement la sécurité à la compilation. La validation à l’exécution nécessite des outils supplémentaires tels que Zod ou des plugins de générateur. Pour les endpoints critiques, associez vos types générés à Zod pour valider les réponses à l’exécution et détecter les bugs backend avant qu’ils n’atteignent votre interface utilisateur.
Conclusion
La génération de code TypeScript OpenAPI est l’une des améliorations à plus fort impact que vous puissiez apporter à une base de code frontend. Choisissez openapi-typescript avec openapi-fetch pour une configuration légère, ou Orval si vous voulez des hooks de requête générés. Dans tous les cas, vous arrêtez d’écrire des types à la main, arrêtez de deviner les formes de réponse, et laissez le compilateur faire le travail pour lequel il a été conçu.
FAQ
Oui. openapi-typescript supporte les spécifications OpenAPI 3.0 et 3.1, bien que certaines fonctionnalités de schéma puissent nécessiter des tests avec votre générateur et spécification spécifiques. Vérifiez toujours la sortie générée après avoir mis à niveau votre version de spécification.
Absolument. Les types générés vous donnent la sécurité à la compilation, tandis que Zod valide les données à l'exécution. Vous pouvez définir des schémas Zod qui reflètent vos types générés et analyser les réponses API à travers eux. Cela détecte les cas où le backend retourne des données inattendues que le compilateur ne peut pas détecter.
Les deux approches fonctionnent. Commiter les fichiers générés rend les builds plus rapides et vous permet de réviser les changements de types dans les pull requests. Régénérer à chaque build garantit que les types sont toujours à jour mais ajoute une dépendance d'étape de build. Choisissez ce qui correspond le mieux au workflow de votre équipe et à votre configuration CI.
Orval est conçu spécifiquement pour TypeScript et produit des hooks TanStack Query, des clients Axios ou des fonctions fetch avec une configuration minimale. OpenAPI Generator supporte de nombreux langages mais produit une sortie TypeScript plus verbeuse. Pour les équipes axées sur le frontend, Orval nécessite généralement moins de personnalisation pour obtenir un code propre et idiomatique.
Complete picture for complete understanding
Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Check our GitHub repo and join the thousands of developers in our community.