Routing is a core concept in web development, enabling your application to handle different HTTP requests at specific endpoints. In this blog, we’ll explore how to implement routing in an Express application using TypeScript, leveraging type safety to build robust APIs. By the end, you’ll understand how to create, organize, and manage routes effectively.
What is Routing in Express?
In Express, routing refers to how an application responds to client requests based on the HTTP method (e.g., GET, POST, PUT, DELETE) and URL path. Each route maps to a specific handler function that processes the request and sends a response.
With TypeScript, we can add type safety to our routes, ensuring that request and response objects are properly typed, reducing errors and improving maintainability.
Prerequisites
Node.js (v16 or higher)
Basic knowledge of Express and TypeScript
Code editor (e.g., VS Code)
Step 1: Set Up the Project
- Initialize the project:
Create a new directory and set up a Node.js project:
mkdir express-ts-routing
cd express-ts-routing
npm init -y
- Install dependencies:
Install Express, TypeScript, and necessary type definitions:
npm install express
npm install --save-dev nodemon typescript ts-node @types/express @types/node
- Set up TypeScript:
Initialize TypeScript configuration:
npx tsc --init
Update tsconfig.json
to include:
{
"compilerOptions": {
"target": "ES2020",
"module": "CommonJS",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true
},
}
- Configure scripts:
Update package.json
with:
"scripts": {
"start": "node dist/server.js",
"build": "tsc p .",
"dev": "nodemon src/server.ts"
}
Step 2: Project Structure
Organize your project for scalability:
express-ts-routing/
├── src/
│ ├── routes/
│ │ ├── userRoutes.ts
│ │ └── postRoutes.ts
│ ├── server.ts
├── package.json
├── tsconfig.json
Step 3: Create the Express Server
Create src/server.ts
to set up the Express server:
import express, { Application } from 'express';
const app: Application = express();
const PORT = 3000;
// Enable URL-encoded form data parsing
app.use(express.urlencoded({ extended: true }));
// Middleware to parse JSON
app.use(express.json());
// Basic route
app.get('/', (req, res) => {
res.send('Welcome to the Express TypeScript API!');
});
// Start server
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
Here, we initialize an Express app, apply URL-encoded middleware for parsing form data and JSON middleware.
Step 4: Define Routes with TypeScript
User Routes
Create src/routes/userRoutes.ts
for user-related endpoints:
import express, { Router, Request, Response } from 'express';
const userRouter: Router = express.Router();
// GET: Fetch all users
userRouter.get('/', (req: Request, res: Response) => {
res.json({ message: 'List of users', users: [] });
});
// GET: Fetch a user by ID
userRouter.get('/:id', (req: Request, res: Response) => {
const id = req.params.id;
res.json({ message: `User with ID ${id}`, user: {} });
});
// POST: Create a user
userRouter.post('/', (req: Request, res: Response) => {
const { name, email } = req.body;
res.json({ message: 'User created', user: { name, email } });
});
// PUT: Update a user
userRouter.put('/:id', (req: Request, res: Response) => {
const id = req.params.id;
const { name, email } = req.body;
res.json({ message: `User ${id} updated`, user: { name, email } });
});
// DELETE: Delete a user
userRouter.delete('/:id', (req: Request, res: Response) => {
const id = req.params.id;
res.json({ message: `User ${id} deleted` });
});
export default userRouter;
Post Routes
Create src/routes/postRoutes.ts
for post-related endpoints:
import express, { Router, Request, Response } from 'express';
const postRouter: Router = express.Router();
// GET: Fetch all posts
postRouter.get('/', (req: Request, res: Response) => {
res.json({ message: 'List of posts', posts: [] });
});
// GET: Fetch a post by ID
postRouter.get('/:id', (req: Request, res: Response) => {
const id = req.params.id;
res.json({ message: `Post with ID ${id}`, post: {} });
});
// POST: Create a post
postRouter.post('/', (req: Request, res: Response) => {
const { title, content } = req.body;
res.json({ message: 'Post created', post: { title, content } });
});
export default postRouter;
Key Points:
Type Safety: The
Request
andResponse
types from Express ensure proper typing for request parameters, body, and response methods.Router: The
express.Router()
method creates modular route handlers, improving code organization.HTTP Methods: Each route handles specific HTTP methods (
GET
,POST
,PUT
,DELETE
) for CRUD operations.
Step 5: Mount the Routes
We import and mount route modules under specific prefixes (/api/users
, /api/posts
) in the server.ts
file.
Here is the updated server.ts
file:
import express, { Application } from 'express';
import userRouter from './routes/userRoutes';
import postRouter from './routes/postRoutes';
const app: Application = express();
const PORT = 3000;
// Enable URL-encoded form data parsing
app.use(express.urlencoded({ extended: true }));
// Middleware to parse JSON
app.use(express.json());
// Mount routes
app.use('/api/users', userRouter);
app.use('/api/posts', postRouter);
// Basic route
app.get('/', (req, res) => {
res.send('Welcome to the Express TypeScript API!');
});
// Start server
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
Step 6: Run the Application
- Start the server:
Run the development server:
npm run dev
The server will start on http://localhost:3000
.
- Test the routes:
Use Postman or cURL to test the endpoints:
GET
http://localhost:3000/api/users
: List all users.POST
http://localhost:3000/api/users
: Create a user (e.g.,{ "name": "John", "email": "john@example.com" }
).GET
http://localhost:3000/api/posts
: List all posts.
Enhancements
Input Validation: Use
express-validator
to validate request bodies and query parameters.Authentication: Integrate JWT or OAuth middleware for secure routes.
Route Prefixing: Group related routes under a common prefix (e.g., /api/users).
Version Your API: Prefix routes with a version (e.g.,
/api/v1/users
) to manage API updates.Documentation: Use tools like Swagger to document your API endpoints.
Conclusion
Routing in Express with TypeScript combines the flexibility of Express with the type safety of TypeScript, resulting in scalable and maintainable APIs. By modularizing routes, typing request/response objects, and following best practices, you can build robust APIs with confidence.
Try extending this setup with a database like MongoDB or adding authentication to secure your routes. Happy coding!
The code for this blog is here.
Top comments (0)