I'm trying to implement a login feature in my app for which I'm using passport for authentication. But I'm getting error on typescript compilation:
TSError: ⨯ Unable to compile TypeScript
server/server.ts (132,26): Argument of type 'PassportStatic' is not
assignable to parameter of type 'Passport'.
Types of property 'use' are incompatible.
Type '{ (strategy: Strategy): PassportStatic; (name: string, strategy: Strategy): PassportStatic; }' is not assignable to type '{ (strategy: Strategy): this; (name: string, strategy: Strategy): this; }'.
Type 'PassportStatic' is not assignable to type 'this'. (2345)
at getOutput (/media/rohan/1084CB1284CAF96C/code/hall3/hall3-server/node_modules/ts-node/src/index.ts:307:15)
at /media/rohan/1084CB1284CAF96C/code/hall3/hall3-server/node_modules/ts-node/src/index.ts:336:16
at Object.compile (/media/rohan/1084CB1284CAF96C/code/hall3/hall3-server/node_modules/ts-node/src/index.ts:496:11)
at Module.m._compile (/media/rohan/1084CB1284CAF96C/code/hall3/hall3-server/node_modules/ts-node/src/index.ts:392:43)
at Module._extensions..js (module.js:580:10)
at Object.require.extensions.(anonymous function) [as .ts] (/media/rohan/1084CB1284CAF96C/code/hall3/hall3-server/node_modules/ts-node/src/index.ts:395:12)
at Module.load (module.js:488:32)
at tryModuleLoad (module.js:447:12)
at Function.Module._load (module.js:439:3)
at Module.require (module.js:498:17)
Here's my code for server.ts :
import * as bodyParser from 'body-parser';
import * as connectMongo from 'connect-mongo';
import * as express from 'express';
import * as session from 'express-session';
import * as cookieParser from 'cookie-parser';
import * as httpLogger from 'morgan';
import * as mongoose from 'mongoose';
import * as passport from 'passport';
import * as path from 'path';
// Config
import { Config } from './config/local';
import { PassportConfig } from './config/passport';
import { logger } from './config/logger';
/**
* The server.
*
* @class Server
*/
export class Server {
// The express app instance
public app: express.Application;
/**
* Bootstrap the application
*
* @class Server
* @method bootstrap
* @static
* @return {ng.auto.IInjectorService} Returns the newly created injector for this app
*/
public static bootstrap = (): Server => {
return new Server();
};
/**
* Constructor.
*
* @class Server
* @constructor
*/
constructor() {
// create expressjs application
this.app = express();
// configure application
this.config();
this.routes();
}
/**
* Configure application
*
* @class Server
* @method config
*/
public config = (): void => {
this.app.use(httpLogger('dev'));
// use json bodyparser
this.app.use(bodyParser.json());
// use query string parser
this.app.use(bodyParser.urlencoded({
extended: true
}));
// use CookieParser for setting and reading cookies
this.app.use(cookieParser(Config.session_secret));
/* some code skipped */
// Set up passport
**PassportConfig.setup(passport, this.userModel);**
this.app.use(passport.initialize());
this.app.use(passport.session()); // persistent login sessions
}
/**
* Create router
*
* @class Server
* @method routes
*/
public routes = () => {
// Backend Admin API Routes
let prefix = '';
//this.app.use(`/accounts`, LoginRoute.create(this.model.localUser, passport));
this.app.use('/data', DataRoute.create());
this.app.use('/files', express.static(path.join(__dirname, 'files')));
};
/**
* Shutdown
*
* @class Server
* @method shutdown
*/
public shutdown = () => {
logger.info('Shutting Down');
this.connection.close();
}
}
And here's my code for PassportConfig :
import { Model } from 'mongoose';
import { Passport } from 'passport';
import { Strategy, IStrategyOptions, VerifyFunction } from 'passport-local';
import { IUserModel } from '../models/user';
export class PassportConfig {
static setup = (passport: Passport, model: Model<IUserModel>) => {
// serialize by username as it is unique <Type of user, type of id>
passport.serializeUser<IUserModel, string>((user: IUserModel, done) => {
// Return unique identification of the user
done(null, user._id);
});
// deserialize by username <Type of user, typeof of id>
passport.deserializeUser<IUserModel, string>((id: string, done) => {
// findbyid and return user
model.findById(id, (err, user: IUserModel) => {
done(err, user);
});
});
// Specify strategy options
let options: IStrategyOptions = {
usernameField: 'username',
passwordField: 'password',
passReqToCallback: false
};
// verify function for signup
let verifySignUp: VerifyFunction = (username: string, password: string, done) => {
process.nextTick(() => {
model.findOne({
'username': username
}, (err, user: IUserModel) => {
if (err) {
return done(err);
}
if (user) {
return done(err, null);
} else {
let newUser = new model();
newUser.username = username;
newUser.password = newUser.generateHash(password);
// save the user
newUser.save((error) => {
return done(error, newUser);
});
}
});
});
};
let verifySignIn: VerifyFunction = (username: string, password: string, done) => {
process.nextTick(() => {
model.findOne({
'username': username
}, (err, user: IUserModel) => {
if (err)
return done(err);
if (!user) {
return done(null, null);
} else if (!user.validPassword(password)) {
return done(null, null);
}
return done(null, user);
});
});
};
passport.use('local-signup', new Strategy(options, verifySignUp));
passport.use('local-signin', new Strategy(options, verifySignIn));
}
}
My Webstorm IDE gives a red underline under passport
on the line PassportConfig.setup(passport, this.userModel);
in my server.ts file.
Please help.
Guessing based just on imports, but it looks like you are importing everything from passport
library in server.ts
:
import * as passport from 'passport';
And so variable passport
is of type PassportStatic
.
And in PassportConfig
you're importing concrete exported class Passport
from library passport
:
import { Passport } from 'passport';
So variable Passport
is of type Passport
.
To fix this you can do several things:
Passport
in server.ts
the same way as in PassportConfig
passport.Passport
in server.ts
(instead of just Passport
)