DEV Community

Extend Express's Request Object with Typescript Declaration Merging.

Kwabena Bio Berko on January 29, 2020

Express has been my go to server side node web framework for the past few years. Its fast, unopinionated and so easy to get up and running. I reall...
Collapse
tjsarkka profile image
TJSarkka

Thank you! I spent the last hours scratching my head and trying different combinations of config files and .d.ts files provided in other solutions.. and this was the only one that worked for me for both ts-node and tsc. :)

Collapse
kwabenberko profile image
Kwabena Bio Berko Author

You're welcome.
Glad to be of help.

Collapse
stevemu profile image
Steve Mu

Thank you so much!!!

Collapse
kwabenberko profile image
Kwabena Bio Berko Author

You're welcome. 😊

Collapse
mxgit1090 profile image
Mark Tsai • Edited

Similar methods to define Request types can also be found in the following libraries:

I also spent so much time resolving this issue, thank you for your article!

Collapse
kwabenberko profile image
Kwabena Bio Berko Author

You're welcome
Really glad you found it useful.

Collapse
alphakennybudy profile image
Adil • Edited

Thank you, it helped. But as far as I understood, it adds currentUser field to all Requests? What if I want it to be present only in the current file and not declared in the other files where I use Request?

Collapse
peterkitonga profile image
Peter Kitonga • Edited

If anyone is still having errors with this, don't forget to import Express at the top of your file.

import { Express } from 'express'

For some reason, I couldn't get it to work without the import

Collapse
damjuve profile image
damjuve

Hello,

Thanks for this very usefull tips.
I still have a question about exporting this.
I would like to extend express Request with UserModel, exactly like you did. But I am doing it in a homemade node module.
Then I install this node module in a node project and I don't have access to the extended request. How can i do this ?

Collapse
aashishclikfin profile image
aashishClikFin • Edited

First of all thanks a lot for your post, I finally resolved the problem I faced since the last 3 months.

Just would like to add one more bit, since I was using passport alongside passport-jwt hence your solution didn't exactly work for me.

Here is what I used in the index.d.ts file

declare module 'express-serve-static-core' {
export interface Request {
user?: yourCustomType;
}
}

It might help someone else as well, but thanks a lot for guiding me in the right direction.

Collapse
georgenorris profile image
George C. Norris

Getting a Augmentations for the global scope can only be directly nested in external modules or ambient module declarations. ??

Collapse
asgamboa12 profile image
Asgamboa12

Thank you very much, this problem was killing me and I could not find a way to solve it until I saw your post, thank you very much !!!

Collapse
sellonen profile image
Sakari Ellonen

I created an account here just to say thank you, this was such a nice solution that a typescript newbie like me would not have come up on my own.

Collapse
kwabenberko profile image
Kwabena Bio Berko Author

I'm really glad you found it useful.

Collapse
justicebringer profile image
Gabriel

NOTE that you have to add typeRoots inside compilerOptions in the tsconfig.json file.

Collapse
hanslissi profile image
riejoc16

Oh wow! I was stuck for a while now trying to achieve exactly that. I couldn't find what I had done wrong. Only with this post I was able to get it done, thanks!

Collapse
kwabenberko profile image
Kwabena Bio Berko Author

You're welcome. 😄

Collapse
renemaldonado profile image
Rene Maldonado Fimbres

Bro, have been having problems with this for 2 days.

Thanks for the info, I was missing the @ sign .

Collapse
kwabenberko profile image
Kwabena Bio Berko Author

You're welcome.

Collapse
vkyrychenko profile image
Vitalii

Nice article! You saved my day 😎👍

I see a lot of libraries using this approach.

But It looks a bit strange for me. Just imagine that you have a lot of middleware that attaches something to the request object. In the end, you have a bloated interface and you lose the power of TypeScript because you don't know which middlewares were executed before handler/controller. So you don't know if the required data was attached and need to double-check if it's there 🤷‍♂️.

Collapse
jpolstre profile image
jpolstre • Edited

Thanks, in my case work whitout: declare global {

Collapse
georgenorris profile image
George C. Norris

I've tried SOO many variations to make this work, and NOTHING seems to work. 🤷🏻‍♂️

Collapse
pendar747 profile image
Pendar

This was awesome! I was missing the step with having to create the same folder path structure and adding the "typeRoots"

Collapse
jonn_joo profile image
Ioannis • Edited

Could you add a GitHub link please. It does not work for me as well.

Collapse
andersonluis87 profile image
Anderson Luis Silva

Thank you very much!
Very well explained.

Collapse
kwabenberko profile image
Kwabena Bio Berko Author

Thank you. 😊

Collapse
tukuyoma profile image
tukuyoma

thanks ...this helped alot

Collapse
terabytes profile image
terabytes

VS code doesn't show error in editor but during compilation i get:
currentUser does not exist on type 'Request'.
Its Ts error.

Collapse
mehmetnyarar profile image
Mehmet N Yarar

same here. not only that, testing (jest/ts-jest) also fails unless I do:

declare module 'express' {
  export interface Request {
    i18n: import('i18next').i18n
    language: string
  }
}
Collapse
sauravbhagat profile image
saurav kumar bhagat

What if we directly extends the Request interface like:
export interface CustomReq extends Request{
currentUser: User
}

and use this instead?

Collapse
kira56 profile image
Diego CS

Thanks!!!!!!!! I was looking for information, but all that I found was not useful, but your explanation goes straight to the point. Than you very much.

Collapse
danfmaia profile image
Dan Maia

The best article about that I've found today in the Internet.