How Do I Amend The Express "Request" Interface Without Using "namespace" In TypeScript?

398 views Asked by At

I'm working on creating a "CurrentUserMiddleware" within NestJS that I can implement globally. I'm using Express (not Fastify) in my implementation of NestJS. I'm trying to update / amend the "Request" interface packaged into "Express" with a new optional key / value pair (field) that is represented by a User Entity in NestJS.

I've resolved the original problem (sort of) by performing a global declaration, adding in the new field accordingly, however I get an error as a result of my linter: ES2015 module syntax is preferred over namespaces.

Looking at the documentation for TypeScript, it seems like the use of namespaces has been deprecated. How can I make my change to the "Request" interface without making the linter mad?

The code for my current-user.middleware.ts file can be found below:

import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
import { UsersService } from '../users.service';
import { User } from '../user.entity';

declare global {
  namespace Express {
    interface Request {
      currentUser?: User;
    }
  }
}

@Injectable()
export class CurrentUserMiddleware implements NestMiddleware {
  constructor(private usersService: UsersService) {}
  async use(req: Request, res: Response, next: NextFunction) {
    const { userId } = req.session || {};

    if (userId) {
      const user = await this.usersService.findOne(userId);

      req.currentUser = user;
    }

    next();
  }
}

I attempted to just perform a general update of the interface, replacing the global declaration with the following:

interface Request {
  currentUser?: User;
  session?: any;
}

But that gives me another error which is Import declaration conflicts with local declaration of 'Request'.

I'm fairly certain this issue could be resolved by removing Request from my import (and it does) but I'm not sure if that action will have any downstream effects that I'm not aware of.

Any guidance you can offer would be very much appreciated!

2

There are 2 answers

0
Jay McDoniel On

Another option, rather than modifying express's types directly, is to create your own interface that extends express's but adds your custom types:

export interface CustomRequest extends Request {
  user: User;
}

The benefit here is a more explicit request type, that's still compatible with other libraries, and it works by default with extra tooling (like ts-jest) without needing extra configuration.

0
Dawid On
import { User } from './user';

declare module 'express' {
  export interface Request {
   user?: User;
  }
}

I had same problem yesterday this is what I did so I guess you can just change user to currentUser