GraphQL vs REST en TypeScript : duel des titans ou choix selon la tâche ?
\n\nLorsque vous codez en TypeScript, la question de l'architecture backend se pose avec une acuité particulière. On ne veut pas simplement "que ça marche", mais que les types volent, que les erreurs soient détectées à la compilation et que le code soit prévisible. Et là, le développeur fait face au choix éternel : le REST éprouvé par le temps ou le GraphQL moderne et flexible ? Les deux technologies s'entendent parfaitement avec TypeScript, mais chacune impose son propre style de développement.
\n\nDans cet article, nous ne ferons pas de remplissage ni ne répéterons des évidences. Nous analyserons GraphQL vs REST en TypeScript avec des exemples concrets, du code, des points sensibles et des scénarios où une approche écrase l'autre. C'est parti !
\n\nREST : un vieil ami qui ne déçoit pas
\n\nREST (Representational State Transfer) est un style architectural où chaque ressource (utilisateur, article, commentaire) a sa propre URL. Vous frappez à /api/users/1 et vous obtenez l'utilisateur. Simple et prévisible. Dans les projets TypeScript, REST est souvent implémenté via Express, Fastify ou NestJS.
Typage dans REST avec TypeScript
\nLe principal problème de REST est le faible couplage entre le backend et le frontend. Vous envoyez du JSON, et le frontend se demande : "Qu'est-ce qui est arrivé ?". TypeScript sauve la mise grâce à des types partagés ou OpenAPI (Swagger).
\n\nExemple : backend avec Express et TypeScript
\n\nimport express, { Request, Response } from 'express';\n\ninterface User {\n id: number;\n name: string;\n email: string;\n}\n\nconst app = express();\napp.get('/api/users/:id', (req: Request, res: Response) => {\n const user: User = { id: +req.params.id, name: 'Alice', email: 'alice@example.com' };\n res.json(user);\n});\n\n\nFrontend (fetch) :
\n\ninterface User {\n id: number;\n name: string;\n email: string;\n}\n\nasync function getUser(id: number): Promise<User> {\n const res = await fetch(`/api/users/${id}`);\n return res.json() as Promise<User>;\n}\n\n\nProblème : si le backend modifie la structure de User, le frontend ne le saura qu'à l'exécution. Les types côté frontend ne sont qu'une copie. Solution : générer les types à partir de la spécification OpenAPI.
\n\nAvantages de REST en TypeScript
\n- \n
- Simplicité de mise en cache : Le cache HTTP (CDN, navigateur) fonctionne nativement. \n
- Structure claire : URL = ressource, méthodes = actions (GET, POST, PUT, DELETE). \n
- Large support : Tout client (navigateur, curl, Postman) comprend REST. \n
- Faible seuil d'entrée : Même un junior comprendra en une heure. \n
Inconvénients de REST
\n- \n
- Sur-récupération et sous-récupération : Vous transportez des champs inutiles ou devez faire plusieurs requêtes. \n
- Structure rigide : Pour obtenir un utilisateur + ses articles, il faut deux requêtes ou des béquilles (champ expand). \n
- Faible typage : Sans OpenAPI, les types côté client ne sont qu'une "promesse". \n
GraphQL : flexibilité et contrôle
\n\nGraphQL est un langage de requêtes qui donne au client le droit de décider lui-même quelles données obtenir. Un seul endpoint (/graphql), une seule requête — et vous obtenez exactement ce que vous avez demandé. TypeScript et GraphQL forment un duo idéal : les types sont générés automatiquement à partir du schéma.
Typage dans GraphQL avec TypeScript
\nD'abord, on écrit le schéma (SDL) :
\n\ntype User {\n id: ID!\n name: String!\n email: String!\n posts: [Post!]!\n}\n\ntype Post {\n id: ID!\n title: String!\n content: String!\n}\n\ntype Query {\n user(id: ID!): User\n}\n\n\nEnsuite, on génère les types (via graphql-codegen) :
// generated.ts\nexport type User = {\n __typename?: 'User';\n id: string;\n name: string;\n email: string;\n posts: Array<Post>;\n};\n\nexport type Post = {\n __typename?: 'Post';\n id: string;\n title: string;\n content: string;\n};\n