Declaration merging doesn't work with express 4.17.* Request type

Viewed 2247

I want to add a property to the Request type, so I created a folder @types/express and in this folder I've added file index.d.ts with this content.

namespace Express {
  interface Request {
    user: number;
  }
}

In VSCode the error has gone while I'm referencing to req.user, and it even shows that user is of type number screenshot that shows that "user" property on the "Request" object is treated right

but when I start the server I see the error that says this:

/home/myself/web/my-server/node_modules/ts-node/src/index.ts:434
    return new TSError(diagnosticText, diagnosticCodes)
           ^
TSError: ⨯ Unable to compile TypeScript:
src/app.ts:46:7 - error TS2339: Property 'user' does not exist on type 'Request<ParamsDictionary, any, any, ParsedQs>'.

46   req.user;
         ~~~~

    at createTSError (/home/myself/web/my-server/node_modules/ts-node/src/index.ts:434:12)
    at reportTSError (/home/myself/web/my-server/node_modules/ts-node/src/index.ts:438:19)
    at getOutput (/home/myself/web/my-server/node_modules/ts-node/src/index.ts:578:36)
    at Object.compile (/home/myself/web/my-server/node_modules/ts-node/src/index.ts:775:32)
    at Module.m._compile (/home/myself/web/my-server/node_modules/ts-node/src/index.ts:858:43)
    at Module._extensions..js (internal/modules/cjs/loader.js:1220:10)
    at Object.require.extensions.<computed> [as .ts] (/home/myself/web/my-server/node_modules/ts-node/src/index.ts:861:12)
    at Module.load (internal/modules/cjs/loader.js:1049:32)
    at Function.Module._load (internal/modules/cjs/loader.js:937:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)

I'd appreciate any ideas on how to fix it.

p.s. I have done the same with express-session module and added a counter property into the Session interface, and it works flawlessly

2 Answers

After loosing a few brain cells I provide myself with answer. To fix the issue I had to recreate folder structure that can be found in this issue https://github.com/microsoft/TypeScript/issues/39581

Then I modified tsconfig.json so its typeRoots would look like this

 "typeRoots": [
      "src/typings/",
      "node_modules/@types/"
    ] 

Then, to augment Request type with my custom types I had to use import expression, so in the end the index.d.ts file would have this inside

declare namespace Express {
  export interface Request {
    user: import("mongoose").Model<import("./../../models/user").User>;
  }
}

tsconfig for the guy in the comments

{
  "compilerOptions": {
               /* Enable incremental compilation */
    "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
    "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
    "lib": [
      "es6"
    ] /* Specify library files to be included in the compilation. */,
    "allowJs": true /* Allow javascript files to be compiled. */,
                     /* Concatenate and emit output to single file. */
    "outDir": "build" /* Redirect output structure to the directory. */,
    "rootDir": "src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
    "strict": true /* Enable all strict type-checking options. */,
    "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
                     /* List of root folders whose combined content represents the structure of the project at runtime. */
    "typeRoots": [
      "src/typings/",
      "node_modules/@types/"
    ] /* List of folders to include type definitions from. */,
    "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,

    /* Advanced Options */
    "resolveJsonModule": true /* Include modules imported with '.json' extension */,
    "skipLibCheck": true /* Skip type checking of declaration files. */,
    "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
  }
}

Related