DBencz
DBencz

Reputation: 1309

How to extend type declaration for TypeScript?

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
    }
}

Upvotes: 1

Views: 550

Answers (2)

DBencz
DBencz

Reputation: 1309

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))
})

Upvotes: 0

Jason Kleban
Jason Kleban

Reputation: 20818

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?: {}
        }
    }
}

Upvotes: 2

Related Questions