1

Below question is similar to: Extend Express Request object using Typescript

I have pretty much tried all combinations listed in the answers and comments without success. Since that one is over 4 years old, I would like to ask the community anew:

In an Express app, I append user property to the request object in the middleware auth.

// index.ts
import express, { Request, Response } from 'express'
.
.
app.get('/test', auth, (req: Request, res: Response) => {
    res.send(welcomeScreen(req.user?.client_name || ''))
})

I get an error:

Property 'user' does not exist on type 'Request<ParamsDictionary, any, any, ParsedQs>'

That is expected. Thus, I want to extend the type definition of the express.Request object to accept my user property, supposedly in a custom d.ts file. But no matter how I try to go about it, I still get the same error. What should be the contents of the d.ts file exactly? My best shot so far is:

// custom.d.ts
namespace Express {
    export interface Request {
        user?: {}
    }
}

After this was added, the user property is recognised in the IDE:

(property) Express.Request.user?: {} | undefined

But I still get the same compile time error. Do I need to change the tsconfig as well? Thanks!

// tsconfig.json
{
    "compilerOptions": {
        "target": "es6",
        "module": "commonjs",
        "outDir": "./compiled",
        "rootDir": "./src",
        "strict": true,
        "moduleResolution": "node",
        "typeRoots": ["./types"],
        "esModuleInterop": true,       "skipLibCheck": true,
        "forceConsistentCasingInFileNames": true
    }
}
DBencz
  • 849
  • 1
  • 9
  • 15
  • 1
    Does this answer your question? [Extend Express Request object using Typescript](https://stackoverflow.com/questions/37377731/extend-express-request-object-using-typescript) – KiraLT Jan 29 '21 at 13:58
  • Can you share the ts configuration file? – tmhao2005 Jan 29 '21 at 14:06
  • 1
    "But I still get the same runtime error." you mean compile time error? And try without specifying typeRoots - just include it among the glob of tsconfig.json's "include"? – Jason Kleban Jan 29 '21 at 17:27
  • I corrected the question, thank you. This is what you mean?```"include": ["./types"]```, it don't seem to work – DBencz Jan 29 '21 at 18:41
  • `"include": "src"` folder or leave it off altogether if your index.ts is just in the project root? I don't think you should have to specify `typeRoots` for this. – Jason Kleban Jan 29 '21 at 20:32

2 Answers2

2

This is a tricky one, because there are a lot of variations that produce similar results, but I think this is the correct answer:

Add @types/express-serve-static-core and then in an express-more.d.ts file:

import { Express } from "express-serve-static-core";

declare global {
    namespace Express {
        interface Request {
            user?: {}
        }
    }
}

Jason Kleban
  • 20,024
  • 18
  • 75
  • 125
0

Here is the solution that worked for our team:

// tsconfig.json
{
  "compilerOptions": {
...
    "typeRoots": [
      "@types",
      "node_modules/@types"
    ],
...
  }
}
// @types/express/index.d.ts
export { }

declare global {
    namespace Express {
        interface Request {
            user?: {}
        }
    }
}

Finally use it as intended:

// src/index.ts
import express, { Request, Response } from 'express'
...
app.get('/test', auth, (req: Request, res: Response) => {
    res.send(welcomeScreen(req.user))
})
DBencz
  • 849
  • 1
  • 9
  • 15