Building Resilient REST APIs with TypeScript and Express
Backend
Back to Articles

Building Resilient REST APIs with TypeScript and Express

Add TypeScript to your Express server the right way. A complete guide to type-safe request validation, error handling middleware, and structuring a scalable API layer.

Suleman Zaheer

Suleman Zaheer|سلیمان ظہیر

Full Stack Developer · UET Lahore, Pakistan

April 18, 20256 min read

The Case for TypeScript on the Backend

JavaScript's flexibility is a double-edged sword. The same dynamic typing that allows rapid prototyping creates subtle bugs that only manifest at runtime — when a user is actively using your application. A function receives undefined where it expects a string. An API response changes its structure and the consuming code silently breaks. TypeScript's static type system catches these entire categories of bugs at compile time — before any code runs.

Project Setup: The Foundation That Matters

A TypeScript Express project requires careful initial configuration. The decisions you make in tsconfig.json set the quality bar for the entire codebase:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitReturns": true,
    "forceConsistentCasingInFileNames": true,
    "skipLibCheck": true
  }
}

strict: true enables all strict type-checking options simultaneously. Never disable it — every strict rule exists because it catches real bugs.

Runtime Validation with Zod: The Missing Piece

TypeScript types are erased at compile time. Your type declarations cannot validate the JSON body of an incoming HTTP request at runtime. Zod provides runtime validation AND generates TypeScript types from your schemas, creating a single source of truth for your data shapes:

import { z } from 'zod';

const CreatePostSchema = z.object({
  title: z.string().min(5).max(200).trim(),
  content: z.string().min(50).max(50000),
  tags: z.array(z.string().max(30)).max(10).optional(),
  published: z.boolean().default(false),
});

type CreatePostInput = z.infer<typeof CreatePostSchema>;

const validate = (schema) => (req, res, next) => {
  const result = schema.safeParse(req.body);
  if (!result.success) {
    return res.status(400).json({ error: 'Validation failed', issues: result.error.issues });
  }
  req.body = result.data;
  next();
};

router.post('/posts', validate(CreatePostSchema), createPostHandler);

Centralized Error Handling with Custom Error Classes

A professional API has a single error handling middleware that processes all errors uniformly. Create an error hierarchy that allows handlers to throw semantically meaningful errors — NotFoundError, UnauthorizedError, ValidationError — that the centralized handler converts to appropriate HTTP responses without leaking internal details.

Type-Safe Request Handlers

Extend Express's Request type to add typed properties that your middleware attaches — authenticated user, validated body, parsed query parameters. This eliminates unsafe type assertions throughout your handler code and makes your route handlers self-documenting about what data they require.

Conclusion

TypeScript with Zod validation and a custom error class hierarchy transforms an Express application from a collection of loosely connected JavaScript functions into a type-safe, validated, professionally structured API. The additional setup cost is 2-3 hours on a new project. The maintenance savings — catching type errors at compile time, self-documenting interfaces, confident refactoring — compound across the entire lifetime of the application.

Topics Covered

TypeScriptNode.jsREST APIBackendExpress

Found this helpful? Share it.

Suleman Zaheer

Written by

Suleman Zaheer | سلیمان ظہیر

Full Stack Developer from Lahore, Pakistan. CS student at UET Lahore. Building production-grade web applications with MERN Stack and Next.js, and writing about real-world software engineering.

Explore More Articles

9 in-depth technical articles on MERN Stack, Next.js, freelancing, UI/UX, and modern backend architecture.

View All Articles