TypeScript + Express + Passport.js - Property id does not exist on type User

Viewed 2004

I'm new to TypeScript, I implemented user authentication using Passport.js in a small app I'm making just for practice.

Problem

I'm trying to tell Passport.js to save the user property id into the session for further authentication, but I just can't find a way to tell TypeScript that the property id of user actually exists.

passport.serializeUser((user, done) => {
  done(undefined, user.id); // Property 'id' does not exists on type 'User' 
});

The parameter user shows off as type Express.User, but it actually is an instance of a TypeOrm entity User. Searching through posts I found out I can extend the type Express.User to add the property that I need to use:

  // src/custom-typings/index.d.ts
  namespace Express {
    interface User {
      id?: number;
    }
  }

Doing this removes the error warning when coding, but when I try to compile the code, the error shows up again, but in my VSCode terminal!.

src/core/passport.ts:38:24 - error TS2339: Property 'id' does not exist on type 'User'.

38   done(undefined, user.id);
                          ~~

    at createTSError (C:\Users\fvg\Desktop\Proyectos\passport-local-example\node_modules\ts-node\src\index.ts:513:12)
    at reportTSError (C:\Users\fvg\Desktop\Proyectos\passport-local-example\node_modules\ts-node\src\index.ts:517:19)
    at getOutput (C:\Users\fvg\Desktop\Proyectos\passport-local-example\node_modules\ts-node\src\index.ts:752:36)
    at Object.compile (C:\Users\fvg\Desktop\Proyectos\passport-local-example\node_modules\ts-node\src\index.ts:968:32)
    at Module.m._compile (C:\Users\fvg\Desktop\Proyectos\passport-local-example\node_modules\ts-node\src\index.ts:1056:42)
    at Module._extensions..js (internal/modules/cjs/loader.js:1157:10)
    at Object.require.extensions.<computed> [as .ts] (C:\Users\fvg\Desktop\Proyectos\passport-local-example\node_modules\ts-node\src\index.ts:1059:12)
    at Module.load (internal/modules/cjs/loader.js:985:32)
    at Function.Module._load (internal/modules/cjs/loader.js:878:14)
    at Module.require (internal/modules/cjs/loader.js:1025:19)

I did add my custom typings into my tsconfig.json:

{
  "compilerOptions": {
    "target": "es5",                       
    "module": "commonjs",                   
    "lib": ["es6"],
    "outDir": "dist",                   
    "rootDir": "src",                         
    "strict": true,                  
    "typeRoots": ["./src/custom-typings", "./node_modules/@types"],                     
    "esModuleInterop": true,
    "experimentalDecorators": true,     
    "emitDecoratorMetadata": true,       
    "resolveJsonModule": true,        
    "skipLibCheck": true,              
    "forceConsistentCasingInFileNames": true
  }
}

This is my project structure:

.
├── src
│   ├── core
│   │     └── passport.ts
│   │  
│   │
│   ├── custom-typings
│   │             └── index.d.ts
│   │
│   └── other stuff
│ 
│
├── tsconfig.json

All other solutions say that this is to way to fix this typical problem, but I just can't make it work, what am I missing?.

3 Answers
  • Install the @types/passport using
    npm install --save @types/passport
    
  • After that open the index.d.ts file, inside the declare global function there is an interface User object. just add whatever variable you want inside it e.g
    declare global {
     namespace Express {
       // tslint:disable-next-line:no-empty-interface
       interface AuthInfo {}
       // tslint:disable-next-line:no-empty-interface
       interface User {
           *username:string;
           yourVariable: any;
           id:number; etc*
       }
    }
    }
    

Use your User class defined in the model instead which should have id. You could also replace id with any other unique identifier in your user type.

passport.serializeUser((user: User, done) => {
  done(undefined, user.id); 
});

Pass any "type" to the user attribute

passport.serializeUser((user:any, done)=>{
    done(null, user.id)
})

Hopefully this helps

Related