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:
- Best open-source ORM and ODM libraries for Node.js
- Node + Express: How to Return XML Response
- Pagination in TypeORM (Find Options & QueryBuilder)
- Node.js: How to Use “Import” and “Require” in the Same File
- How to easily generate a random string in Node.js
- Node.js: Reading content from PDF and CSV files
You can also check out our Node.js category page for the latest tutorials and examples.
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?
You can use the Non-null assertion operator to tell typescript it is definitely not undefined/null like this –
user = req.user!