Express + TypeScript: Extending Request and Response objects

Last updated on October 21, 2021 The Plumber Loading... One comment

This article shows you how to add new properties to an Express request object (we often deal with this task when working with middleware) or an Express response (not too common but may be necessary in some certain cases) object in a Node.js project that is written in TypeScript.

Prerequisites

To follow this tutorial, you need the following:

  • A basic understanding of Node.js, Express.js, and TypeScript
  • Know how to setup a Node project with TypeScript

The Solution

Our strategy is to declare a custom type, like this:

import { Request, Response, NextFunction } from 'express';

// Declaring custom request interface
// We export this interface so that we can use it in other places in our project
export interface CustomRequest extends Request {
  foo?: string;
  bar?: number;
}

const myMiddleware = (req: CustomRequest, res: Response, next: NextFunction) => {
  const foo = 'foo';
  const bar = 123;

  req.foo = foo;
  req.bar = bar;

  next();
}

export default myMiddleware;

You can also extend your Express response object in the same way:

import { Request, Response } from 'express';

interface CustomResponse extends Response {
  customProperty?: string;
}

const myController = (req: Request, res: CustomResponse, next: NextFunction ) => {
  res.customProperty = 'Some thing';
  /* Other code go here */
}

For more clarity, please move on to the next section of this article.

The Complete Example

1. For simplicity’s sake, our sample project will have only 2 files in the src folder: index.ts and my-middleware.ts:

.
├── index.ts
└── my-middleware.ts

Screenshot:

2. Full source code in my-middleware.ts:

import { Request, Response, NextFunction } from 'express';

interface User {
  id: string;
  email: string;
  role: string;
}

// Declaring custom request interface
export interface CustomRequest extends Request {
  user?: User,
  foo?: string;
  bar?: number;
}

const myMiddleware = (req: CustomRequest, res: Response, next: NextFunction) => {
  const user: User = {
    id: 'u1',
    email: '[email protected]',
    role: 'author'
  }

  const foo = 'foo';
  const bar = 123;

  req.user = user;
  req.foo = foo;
  req.bar = bar;

  next();
}

export default myMiddleware;

3. Full source code in index.ts:

import express, { NextFunction, Request, Response } from 'express';

// import middleware
import myMiddleware, { CustomRequest } from './my-middleware';

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

app.get('/', (req: CustomRequest, res: Response) => {
  res.status(200).json({
    user: req.user,
    foo: req.foo,
    bar: req.bar,
    message: 'Welcome to KindaCode.com'
  });
});

app.listen(3000, () => {
  console.log('Backend is running on port 3000');
})

4. Check it out by heading to http://localhost:3000 with Postman or a web browser:

Conclusion

We’ve explored an elegant approach to add our custom properties to request and response objects of Express.js. If you’d like to learn more new and exciting things about modern Node.js development, take a look at the following articles:

You can also check out our Node.js category page for the latest tutorials and examples.

Subscribe
Notify of
guest
1 Comment
Inline Feedbacks
View all comments
David
David
24 days ago

Given that the CustomRequest interface must specify its properties as optional, how do you now avoid typescript errors in the route handler for each property: Object is possibly undefined ?

How do we tell typescript “The middleware has definitely defined it” without littering ignore comments everywhere?

Related Articles