TypeScript brings type safety to server-side JavaScript. This chapter covers typing Express routes, middleware, and common Node.js patterns.

Project Setup

  mkdir my-api && cd my-api
npm init -y
npm install express
npm install --save-dev typescript @types/node @types/express tsx
npx tsc --init
  

Update tsconfig.json:

  {
  "compilerOptions": {
    "target": "ES2020",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true
  },
  "include": ["src/**/*"]
}
  

Add to package.json:

  {
  "type": "module",
  "scripts": {
    "dev": "tsx watch src/index.ts",
    "build": "tsc",
    "start": "node dist/index.js"
  }
}
  

Basic Express Server

  // src/index.ts
import express, { Request, Response } from 'express';

const app = express();
app.use(express.json());

app.get('/health', (_req: Request, res: Response) => {
    res.json({ status: 'ok' });
});

const PORT = 3000;
app.listen(PORT, () => {
    console.log(`Server running on http://localhost:${PORT}`);
});
  

Run with npm run dev.

Typed Route Handlers

  interface User {
    id: number;
    name: string;
    email: string;
}

interface CreateUserBody {
    name: string;
    email: string;
}

const users: User[] = [
    { id: 1, name: 'Alice', email: '[email protected]' }
];

app.get('/users', (_req: Request, res: Response<User[]>) => {
    res.json(users);
});

app.post('/users', (req: Request<object, User, CreateUserBody>, res: Response<User>) => {
    const { name, email } = req.body;
    const user: User = { id: Date.now(), name, email };
    users.push(user);
    res.status(201).json(user);
});
  

Generic parameters on Request: Request<P, ResBody, ReqBody, ReqQuery>.

Error Handling

  import { NextFunction } from 'express';

interface ApiError {
    error: string;
    code: number;
}

app.use((err: Error, _req: Request, res: Response<ApiError>, _next: NextFunction) => {
    console.error(err.message);
    res.status(500).json({ error: 'Internal server error', code: 500 });
});
  

Build and Deploy

  npm run build   # compiles src/ → dist/
npm start       # runs dist/index.js
  

TypeScript on the server catches API contract bugs before they reach production. Combine this with the React chapter for full-stack typed development.