Utilizing the functionality of TypeScript to extend the Request type in Express allowing us to pass our own types to be used with the Request object.
In the example below, I wanted to be able to add a services
key to the Express Request object and pass interfaces for Query
, Params
and Body
.
I also reordered some of the types in order of what I most frequently used, making everything optional.
// types.ts
import * as core from 'express-serve-static-core'
import {
ReportService,
} from './services'
interface IRequestServices {
ReportService: () => ReportService,
}
export interface Query extends core.Query { }
export interface Params extends core.ParamsDictionary { }
export interface Request<ReqBody = any, ReqQuery = Query, URLParams extends Params = core.ParamsDictionary>
extends express.Request<URLParams, any, ReqBody, ReqQuery> {
services: IRequestServices,
}
// controller.ts
import express from 'express'
import { Params, Query, Request } from '../../types'
interface RequestBody {
name: string
}
interface RequestQuery extends Query {
category: string
}
interface RequestParams extends Params {
reportId: string
}
const updateNameController = async (req: Request<RequestBody, RequestQuery, RequestParams>, res: express.Response): Promise<void> => {
const reportService = req.services.ReportService()
const report = await reportService.updateReportName(req.params.reportId, req.query.category, req.body.name)
return res.status(200)
}
export default updateNameController
Let me know your thoughts in the comments!
Top comments (3)
Any better way to handle the case where we do not need to extend body and params but only need to extend the Query, example in Get Request for list of items
doing this is kind of messy,
Request<never, never, never, Query>
any suggestions?
You could rearrange the generics in the interface if your use case is generally using one over the others.
Alternatively, you may create more interfaces that default the others.
eg.
RequestWithQuery<Query>
Very helpful, thank you