How to make Express with Typescript and Passport "user" required after middleware?


I have to keep doing stuff like

if (!req.user) return res.status(401).send()

The approach the comes into mind would be an express middleware for that. But even tho I can prevent non-logged users from reaching the route I can’t think of a way to type express req correctly.

If I override the "req" param the router complains because the user key in "Express.User" is an optional parameter.

I don’t believe changing the global override so "user" is required is a good option since "user" should only be required after the middleware validation. How can I achieve this?

Below some piece of useful code to understand the context.

Global Express Override

declare global {
  namespace Express {
    interface User extends TUser {
      _id: ObjectId

What I want to achieve

// Router'/', sessionMiddleware, controller)

// Middleware
const sessionMiddleware = (req: Request, res: Response, next: NextFunction) => {
if (!req.user) return res.status(401).send()

// Controller
const controller = (req: RequestWithRequiredUser, res: Response) => {
  // user here can't possibly be typed undefined
  const user = req.user

What I actually have to do everytime:

const controller = (req: Request, res: Response) => {
  if (!req.user) return res.status(401).send()



I don’t if better solution with middlewares are available but this is a workaround I found to avoid repeating logic.


/** Make given keys required */
export type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] }

type TController<T extends Request> = (req: WithRequired<T, 'user'>, res: Response) => unknown

export const buildSessionController =
  <T extends Request>(controller: TController<T>) =>
  (req: Request, res: Response) => {
    if (!req.user) return res.status(401).send()

    // This is needed as a type workaround because a type mismatch happens otherwise
    // Using Omit instead of WithRequired above doesn't fix it
    const request = req as WithRequired<T, 'user'>

    return controller(request, res)


export const expressController = 
  buildSessionController((req, res) => {
    // user will never be undefined here
    const { user } = req

    return res.json(user)

Answered By – Luna

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published