TypeScript with Express
Building type-safe backend applications
⚡ What is TypeScript with Express?
TypeScript brings type safety to Express.js applications, helping you build robust backend APIs with better error handling, autocomplete, and maintainable code for server-side development.
// Basic Express server with TypeScript
import express, { Request, Response } from 'express'
const app = express()
app.get('/', (req: Request, res: Response) => {
res.send('Hello TypeScript!')
})
Key Features
Type Safety
Catch errors at compile time
interface User {
id: number
name: string
}
Typed Routes
Define routes with type checking
app.get('/user/:id',
(req, res) => {
// typed params
})
Middleware Types
Type-safe middleware functions
const logger:
RequestHandler =
(req, res, next) => {
next()
}
Request/Response
Typed request and response objects
req: Request
res: Response
next: NextFunction
🔹 Basic Express Server Setup
Create a simple Express server with TypeScript:
import express, { Express, Request, Response } from 'express'
const app: Express = express()
const port = 3000
// Middleware
app.use(express.json())
// Basic route
app.get('/', (req: Request, res: Response) => {
res.json({ message: 'Hello from TypeScript Express!' })
})
// Start server
app.listen(port, () => {
console.log(`Server running on port ${port}`)
})
Output:
Server running on port 3000
🔹 Typed Route Parameters
Define types for route parameters and query strings:
import { Request, Response } from 'express'
// Define parameter types
interface UserParams {
id: string
}
// Define query types
interface UserQuery {
name?: string
age?: string
}
// Typed route handler
app.get('/user/:id',
(req: Request<UserParams, {}, {}, UserQuery>, res: Response) => {
const userId = req.params.id
const userName = req.query.name
res.json({
id: userId,
name: userName
})
}
)
🔹 Typed Request Body
Create type-safe POST requests with body validation:
import { Request, Response } from 'express'
// Define request body type
interface CreateUserBody {
name: string
email: string
age: number
}
// POST route with typed body
app.post('/users',
(req: Request<{}, {}, CreateUserBody>, res: Response) => {
const { name, email, age } = req.body
// TypeScript knows the types!
const newUser = {
id: Date.now(),
name,
email,
age
}
res.status(201).json(newUser)
}
)
🔹 Custom Middleware with Types
Create reusable typed middleware functions:
import { Request, Response, NextFunction, RequestHandler } from 'express'
// Logger middleware
const logger: RequestHandler = (
req: Request,
res: Response,
next: NextFunction
) => {
console.log(`${req.method} ${req.path}`)
next()
}
// Auth middleware
const authenticate: RequestHandler = (req, res, next) => {
const token = req.headers.authorization
if (!token) {
return res.status(401).json({ error: 'Unauthorized' })
}
next()
}
// Use middleware
app.use(logger)
app.get('/protected', authenticate, (req, res) => {
res.json({ message: 'Protected route' })
})
🔹 Error Handling with Types
Implement type-safe error handling:
import { Request, Response, NextFunction, ErrorRequestHandler } from 'express'
// Custom error class
class AppError extends Error {
statusCode: number
constructor(message: string, statusCode: number) {
super(message)
this.statusCode = statusCode
}
}
// Error handling middleware
const errorHandler: ErrorRequestHandler = (
err: AppError,
req: Request,
res: Response,
next: NextFunction
) => {
const statusCode = err.statusCode || 500
const message = err.message || 'Internal Server Error'
res.status(statusCode).json({
error: message,
statusCode
})
}
// Use error handler
app.use(errorHandler)