GraphQL vs REST in TypeScript: Duell der Titanen oder Wahl nach Aufgabe?
\n\nWenn Sie in TypeScript schreiben, stellt sich die Frage nach der Backend-Architektur besonders dringend. Man möchte nicht nur, dass es "funktioniert", sondern dass Typen fliegen, Fehler zur Kompilierungszeit abgefangen werden und der Code vorhersagbar ist. Und hier steht der Entwickler vor der ewigen Wahl: das bewährte REST oder das moderne, flexible GraphQL? Beide Technologien harmonieren hervorragend mit TypeScript, aber jede diktiert ihren eigenen Entwicklungsstil.
\n\nIn diesem Artikel werden wir keine Allgemeinplätze wiederholen. Wir analysieren GraphQL vs REST in TypeScript an konkreten Beispielen, mit Code, Engpässen und Szenarien, in denen ein Ansatz den anderen übertrifft. Los geht's!
\n\nREST: Ein alter Freund, der nicht enttäuscht
\n\nREST (Representational State Transfer) ist ein Architekturstil, bei dem jede Ressource (Benutzer, Beitrag, Kommentar) ihre eigene URL hat. Sie greifen auf /api/users/1 zu und erhalten den Benutzer. Einfach und vorhersagbar. In TypeScript-Projekten wird REST oft mit Express, Fastify oder NestJS implementiert.
Typisierung in REST mit TypeScript
\nDer Hauptschmerz von REST ist die schwache Verbindung zwischen Backend und Frontend. Sie senden JSON, und das Frontend rätselt: "Was ist da angekommen?". TypeScript rettet durch gemeinsame Typen oder OpenAPI (Swagger).
\n\nBeispiel: Backend mit Express und 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\nProblem: Wenn das Backend die User-Struktur ändert, erfährt das Frontend davon erst zur Laufzeit. Die Typen im Frontend sind nur eine Kopie. Lösung: Generierung von Typen aus der OpenAPI-Spezifikation.
\n\nVorteile von REST in TypeScript
\n- \n
- Einfaches Caching: HTTP-Cache (CDN, Browser) funktioniert sofort. \n
- Klare Struktur: URL = Ressource, Methoden = Aktionen (GET, POST, PUT, DELETE). \n
- Breite Unterstützung: Jeder Client (Browser, curl, Postman) versteht REST. \n
- Niedrige Einstiegshürde: Selbst ein Junior versteht es in einer Stunde. \n
Nachteile von REST
\n- \n
- Over-fetching und Under-fetching: Sie ziehen entweder unnötige Felder oder machen mehrere Anfragen. \n
- Starre Struktur: Um einen Benutzer + seine Beiträge zu erhalten, braucht man zwei Anfragen oder Workarounds (expand-Feld). \n
- Schwache Typisierung: Ohne OpenAPI sind die Typen auf dem Client nur ein "Ehrenwort". \n
GraphQL: Flexibilität und Kontrolle
\n\nGraphQL ist eine Abfragesprache, die dem Client das Recht gibt, selbst zu entscheiden, welche Daten er erhält. Ein Endpunkt (/graphql), eine Anfrage – und Sie erhalten genau das, was Sie bestellt haben. TypeScript und GraphQL sind ein ideales Paar: Typen werden automatisch aus dem Schema generiert.
Typisierung in GraphQL mit TypeScript
\nZuerst wird das Schema (SDL) geschrieben:
\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\nDann werden die Typen generiert (über 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