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

When trying to extend the Request interface from the package express to add some custom properties, I'm getting the following typescript error on my routers:

..\node_modules\ts-node\src\index.ts:434
    return new TSError(diagnosticText, diagnosticCodes)
           ^
   TSError:  Unable to compile TypeScript:
    src/app/middlewares/Authentification.ts:20:13 - error TS2339: Property 'user' does not exist on type 
   'Request<ParamsDictionary, any, any, ParsedQs>'.

   20         req.user = id;
    ....

I searched google for almost two days and none of them got a definite answer. The codes are working on my old project, but if I create a new project and use it, the above error occurs.

Now I'm using thoose packages:

  • ts-node 8.10.2

  • typescript 3.9.7

  • express 4.17.1

  • @types/node 14.6.0

  • Now I'm using the latest stable version Typscript, express, Jsonwebtokens, TypeOrm and etc. My tsconfig.json file follow that:

{
   "compilerOptions": {
      "target": "es5",
      "module": "commonjs",
       "lib": ["es5",  "es6", "dom"
       ],
       "outDir": "./build",
       "emitDecoratorMetadata": true,
       "experimentalDecorators": true,
       "sourceMap": true,
      "moduleResolution": "node",
      "esModuleInterop": true,
      "allowJs": true,
      "noEmit": true,
      "noUnusedLocals": true,
      "noUnusedParameters": false,
      "preserveConstEnums": true,
      "skipLibCheck": true,
      "strict": true,
      "forceConsistentCasingInFileNames": true,
      "isolatedModules": true,
      "strictPropertyInitialization": false, /* Enable strict checking of property initialization in classes. */

   },
   "files": ["./src/types.d.ts", "./node_modules/@types/node/index.d.ts"],
   "include": ["src/**/*.ts"],
   "exclude": ["node_modules"],
   "typeRoots": ["./node_modules/@types"]
}
  • My type-d.ts file follow as:
declare namespace Express {
  import { User } from "./app/entity/User";
  export interface Request {
    user?: User;
   // Alse tried as 
   // user: string
  // user?: string
  // user: any ...
  }
}
  • My Router file follow as:
import bodyParser from "body-parser";
import express from "express";
import socket from "socket.io";
import {RegValidation, SignValidation } from "./../util";
import {UserCtrl, AuthCtrl} from "./../app/controller";
import Authentification from "./../app/middlewares/Authentification";
import cors from "cors";

const createRoutes = (app: express.Express, io: socket.Server) => {

    const options: cors.CorsOptions = {
        allowedHeaders: ["Origin", "X-Requested-With", "Content-Type", "Accept", "X-Access-Token"],
        credentials: true,
        methods: "GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE",
        origin: true,
        //origin: "*",
        optionsSuccessStatus: 204, // some legacy browsers (IE11, various SmartTVs) choke on 204
        preflightContinue: false
    };
    
    // declare controllers
    const UserController = new UserCtrl(io);
    // AuthCtrl
    const Auth = new AuthCtrl();

    app.use(cors());
    //enable pre-flight
    app.options( "*", cors(options));

    //Load files via URL
    app.use(express.static('public'));
    app.use(bodyParser.json());

    app.get( "/", Authentification, (_: express.Request, res: express.Response) => {
        res.send("Hello, World!");
    });

    // API for Users CRUD
    app.post("/user/register", RegValidation, UserController.create);
    app.post( "/user/login", SignValidation, Auth.authenticate);
};
export default createRoutes;
  • And my middlewere file follw as:
import { Request, Response, NextFunction } from 'express'
import jwt from 'jsonwebtoken';

interface TokenPayload {
    id: string;
    iat: number;
    exp: number;
}

export default function AuthController ( req: Request, res: Response, next: NextFunction ) {
    const { authorization } = req.headers;
    if ( !authorization ) {
        res.send( 401 )
    }

    const token = authorization!.replace( 'Bearer', '' ).trim();
    try {
        const data = jwt.verify( token, 'BATMAN' );
        const { id } = data as TokenPayload;
        req.user = id;

        return next();
    } catch{
        res.sendStatus( 401 )
    }
}
// Also i tried with another codes but no solution
  • My User model follow as:
@Entity( 'users' )
export class User {

    @PrimaryGeneratedColumn()
    id!: number;

    @Column({
        type: "varchar",
        length: 60,
    })
    first_name!: string;

    @Column({
        type: "varchar",
        length: 60,
    })
    last_name!: string;

    @Column({
        type: "varchar",
        length: 60,
        default: null,
        unique: true,
    })
    username!: string;

    @Column({
        type: "varchar",
        length: 60,
        unique: true,
    })
    email!: string;

    @Column({
        type: "varchar",
        default: "uploads/avatar.png"
    })
    avatar!: string;

    @Column({
        default: null,
    })
    birthday!: Date;

    @Column({
        default: null,
    })
    last_seen!: Date;

    @Column({
        default: true,
    })
    confirmed!: Boolean;

    @Column({
        default: true,
    })
    is_active!: Boolean;

    @Column({
        type: "varchar",
    })
    password!: string;

    @CreateDateColumn({ type: 'timestamp' })
    created_at!: Date;

    @UpdateDateColumn({ type: 'timestamp' })
    updated_at!: Date;

The codes are the same, working on my old project. But that is making an error in new project. Can anyone help?

23 Answers

✔️Accepted Answer

Man, I solved, try using --files after ts-node script:

ts-node-dev --files

Other Answers:

If you're using ts-node and not ts-node-dev, do this:

  1. Create a typings folder in your src folder.
  2. Create a folder within the typings folder with the name of the package you intend to extend.
  3. Create an index.d.ts file with the new folder.

In my case, I am extending express, I ended up with something like this:

  src/
    - typings/
      - express/
        - index.d.ts

within the index.d.ts file I have this:

declare module Express {
    export interface Request {
        bucketUrl: string;
        fileName: string;
    }
}

Remember to update your .tsconfig:

{
  "compilerOptions": {
    "typeRoots" : ["./node_modules/@types", "./typings"]
  }
}

Hello, I got the same issue as you. How you managed to fix the error?

Try to change declare namespace Express to declare module 'express'
like this:

import 'express';

declare module 'express' {
  interface Request {
    user?: any;
  }
}

In my case, I used the latest version of express: express@4.17.1 and typescript@4.2.4

Português:

Pessoal eu estava tendo o mesmo problema, rodei vários sites e não resolvia! Eu apenas inverti a ordem no tsconfig.json do "typeRoots"[

  "./node_modules/@types",
   "./src/@types",
], 

para [
"./src/@types",
"./node_modules/@types",
],

##English:

Guys I was having the same problem, I ran several sites and it didn't solve it! I just reversed the order in tsconfig.json from

"typeRoots"[
"./node_modules/@types",
"./src/@types",
],

to [
"./src/@types",
"./node_modules/@types",
],

More Issues: