Jose Carlos Filho
Jose Carlos Filho

Reputation: 53

How extends correctly the headers of Request in Typescript

I need the userId in req.headers, but I can't type it correctly, how do I do this?

First I tried to do this:

  interface ISpot{
    thumbnail: File,
    company: string,
    price: number,
    techs: string
  }

  interface IReqCustom<T> extends Request{
    body: T,
  }

  export default {
    async store (req: IReqCustom<ISpot>, res: Response): Promise<Response> {
      const { filename } = req.file
      const { company, techs, price } = req.body
      const { userId } = req.headers

      const user = await User.findById(userId)

      if (!user) {
        return res.status(400).json({ error: 'User doesn\'t exist' })
      }

      const spot = await Spot.create({
        user: userId,
        thumbnail: filename,
        company,
        techs: techs.split(',').map(tech => tech.trim()),
        price
      })

      return res.json(spot)
    }

}

The user key on line 34 is necessarily a string, but the value it is receiving from userId is string | string [] | undefined.

I tried this too:


interface UserHeader{
  userId: string
}

interface IReqCustom<T, P> extends Request{
  body: T,
  headers: P
}

async store (req: IReqCustom<ISpot, UserHeader>, res: Response): Promise<Response>{}

The error in atribuition of user disappear but appear another error in interface IReqCustom:

Interface 'IReqCustom<T, P>' incorrectly extends interface 'Request<ParamsDictionary, any, any, ParsedQs>'.
  Types of property 'headers' are incompatible.
    Type 'P' is not assignable to type 'IncomingHttpHeaders'.

How do I make these attributes recognize their respective types?

Upvotes: 5

Views: 3858

Answers (1)

gurisko
gurisko

Reputation: 1182

You need to take IncomingHttpHeaders (which is the type returned by express.Request.headers) and extend/intersect it with your custom headers type:

import {Request, Response} from 'express';
import {IncomingHttpHeaders} from 'http';

interface ISpot{
  thumbnail: File,
  company: string,
  price: number,
  techs: string
}

interface CustomHeaders {
  userId: string;
}

interface IReqCustom<TBody, THeader> extends Request {
  body: TBody;
  headers: IncomingHttpHeaders & THeader;
}

export const handler = (req: IReqCustom<ISpot, CustomHeaders>, res: Response) => {
  const {userId} = req.headers; // `userId` is now `string`
  return res.status(200);
}

Upvotes: 5

Related Questions