GraphQL vs REST in TypeScript: What to Choose for Your Project

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

GraphQL vs REST in TypeScript: A Clash of Titans or a Choice Based on the Task?

\n\n

When you write in TypeScript, the question of backend architecture becomes especially acute. You want not just "for it to work," but for types to fly, errors to be caught at compile time, and code to be predictable. And here the developer faces the eternal choice: the time-tested REST or the trendy, flexible GraphQL? Both technologies work great with TypeScript, but each dictates its own development style.

\n\n

In this article, we won't beat around the bush or state the obvious. We will break down GraphQL vs REST in TypeScript with specific examples, code, bottlenecks, and scenarios where one approach outperforms the other. Let's go!

\n\n

REST: An Old Friend That Doesn't Let You Down

\n\n

REST (Representational State Transfer) is an architectural style where each resource (user, post, comment) has its own URL. You hit /api/users/1 and get the user. Simple and predictable. In TypeScript projects, REST is often implemented via Express, Fastify, or NestJS.

\n\n

Typing in REST with TypeScript

\n

The main pain point of REST is the weak link between the backend and frontend. You send JSON, and the frontend guesses: "What came back?" TypeScript saves the day through shared types or OpenAPI (Swagger).

\n\n

Example: Backend on Express with TypeScript

\n\n
import 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\n

Frontend (fetch):

\n\n
interface 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\n

Problem: if the backend changes the User structure, the frontend will only find out at runtime. The types on the frontend are just a copy. Solution: generate types from the OpenAPI specification.

\n\n

Pros of REST in TypeScript

\n
    \n
  • Simplicity of caching: HTTP cache (CDN, browser) works out of the box.
  • \n
  • Clear structure: URL = resource, methods = actions (GET, POST, PUT, DELETE).
  • \n
  • Wide support: Any client (browser, curl, Postman) understands REST.
  • \n
  • Low entry barrier: Even a junior can figure it out in an hour.
  • \n
\n\n

Cons of REST

\n
    \n
  • Over-fetching and Under-fetching: You either pull extra fields or make multiple requests.
  • \n
  • Rigid structure: To get a user + their posts, you need two requests or workarounds (expand field).
  • \n
  • Weak typing: Without OpenAPI, types on the client are just a "promise."
  • \n
\n\n

GraphQL: Flexibility and Control

\n\n

GraphQL is a query language that gives the client the right to decide for itself what data to receive. One endpoint (/graphql), one request — and you get exactly what you ordered. TypeScript and GraphQL are a perfect pair: types are automatically generated from the schema.

\n\n

Typing in GraphQL with TypeScript

\n

First, the schema (SDL) is written:

\n\n
type 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\n

Then types are generated (via graphql-codegen):

\n\n
// 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

                
                

Blogs

Book Recommendations