2

I'd like to expose a value to all request handlers using express & typescript. I'd like to be able to "inject" this value from a middleware (or some other way), the point is that it should be easy to mock it in case I need to.

I came up with this solution:

// The context type, I'd like to be able to inject this using the middleware below. 
// In a real scenario think of this like a database connection, etc.
type RequestContext = {
  foo: string
}

// The type enriching the Request type with the context field
type HasContext = {
  context: RequestContext
}

// Middleware attaching the context to the request
const contextMiddleware =
  (context: RequestContext) => 
  (req: Request & Partial<HasContext>, _res: Response, next: NextFunction) => {
    req.context = context
    next()
  }


// Now an actual route using the extra type
const mainRoute = express.Router().get('/test', (req: Request & HasContext, res) => {
  res.json({ context: req.context })
})

// Adding the middlewares and listen
app.use(contextMiddleware({ foo: 'bar' }))
app.use(mainRoute)

app.listen(8000)

My questions:

  • Is this the intended way of doing this using express? I scouted the API but couldn't find a better solution
  • The extra data is attached to the request. Is there any other way that does this without mutating the request or response itself?
  • The type Request & HasContext has to be defined in each request that uses this context. Is there a better way?
3
  • You can define a custom type for Request & HasContext somewhere and import it Commented Oct 11, 2021 at 17:38
  • @Phix I know, not really the point of the question. Still for each request handler I have to use the custom type. Commented Oct 11, 2021 at 17:42
  • See this question and the answer stackoverflow.com/q/58787934/1915893. It shows how you can augment the types in the express package based Commented Oct 11, 2021 at 17:55

1 Answer 1

7

You can overwrite the express Request interface to include your context property. This way you don't have to specify the type anywhere. It will also keep all the other properties that Request normally has.

declare global {
  namespace Express {
    interface Request {
      context: RequestContext 
    }
  }
}

I would recommend not using the Request object to store information. Express recommends the use of the res.locals property.

Sign up to request clarification or add additional context in comments.

1 Comment

Awesome, thanks, that's what I was looking for, response.locals it is then.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.