【问题标题】:Typescript declaration merging errors with passport, passport-local and express-session打字稿声明将错误与护照、本地护照和特快会话合并
【发布时间】:2022-11-13 16:36:11
【问题描述】:
  • 我正在努力使用 Typescript 获得护照、本地护照和快速会话工作。
  • 我已经安装了所有 4 个所需的库,即 @types/passport、@types/express-session @types/passport-local 和 @types/express。我打算使用connect-redis将所有会话存储在redis数据库中

我目前收到 2 个错误

Property 'emailVerified' does not exist on type 'User'

Property 'id' does not exist on type 'User'

我尝试根据HEREHEREHERE 的一些答案创建声明,这些似乎都不起作用。如果有人能告诉我哪里出错了,我将不胜感激

tsconfig.json

{
  "compilerOptions": {
    "lib": ["es2020"],
    "module": "commonjs",
    "moduleResolution": "node",
    "target": "es2020",
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "noImplicitAny": false,
    "outDir": "dist",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "baseUrl": ".",
    "paths": {
      "server/*": ["src/server/*"],
      "tests/*": ["src/tests/*"],
      "data/*": ["src/data/*"],
      "config": ["src/config"]
    },
    "typeRoots": ["./src/@types", "./node_modules/@types"]
  }
}

src/@types/express/index.d.ts

declare global {
  export namespace Express {
    export interface User {
      id: string;
      emailVerified: boolean;
    }
  }
}

护照.ts

import { Express, Request } from 'express';
import passport from 'passport';
import {
  IStrategyOptionsWithRequest,
  IVerifyOptions,
  Strategy as LocalStrategy,
} from 'passport-local';
import { AuthService } from 'server/services';
import { isHashEqual } from 'server/utils/functions';

const strategyOptions: IStrategyOptionsWithRequest = {
  usernameField: 'email',
  passwordField: 'password',
  passReqToCallback: true,
};

passport.serializeUser(
  (
    user: Express.User,
    done: (err: any, user?: Express.User | false | null) => void,
  ) => {
    console.debug('serializeUser called with user %o', user);
    done(null, user.id);
  },
);
passport.deserializeUser(
  async (
    accountId: string,
    done: (err: any, user?: Express.User | false | null) => void,
  ) => {
    try {
      const user = await AuthService.get(accountId);
      if (typeof user !== 'undefined' && user !== null) {
        console.debug(
          'deserializeUser found user %o for accountId %s',
          user,
          accountId,
        );
        done(null, user.toJSON());
      } else {
        console.debug(
          'deserializeUser did not find user for accountId %s',
          accountId,
        );
        done(null, false);
      }
    } catch (error) {
      console.error(error, 'deserializeUser encountered an error');
      done(error, false);
    }
  },
);

passport.use(
  'local',
  new LocalStrategy(
    strategyOptions,
    async (
      req: Request,
      email: string,
      password: string,
      done: (error: any, user?: any, options?: IVerifyOptions) => void,
    ) => {
      try {
        const account = await AuthService.getByEmail(email);
        if (!account) {
          console.debug('LocalStrategy incorrect email');
          return done(null, false, { message: 'Incorrect email or password' });
        }
        if (!(await isHashEqual(password, account.password))) {
          console.debug('LocalStrategy password not matching with hash');
          return done(null, false, { message: 'Incorrect email or password' });
        }
        delete account.password;
        // Dont log the user account object before you delete the password
        console.debug('LocalStrategy returning account %o', account);
        return done(null, account);
      } catch (error) {
        console.error(error, 'LocalStrategy encountered an error');
        return done(error);
      }
    },
  ),
);

和控制器文件

身份验证控制器.ts

  static async verifyEmail(req: Request, res: Response, next: NextFunction) {
    try {
      const { accountId, token } = req.params;
      const result = await VerificationTokenService.getNonExpired(accountId);
      if (!result) {
        return next(
          new IncorrectAccountIdOrExpiredToken(
            'Incorrect account id or expired token',
          ),
        );
      }
      if (!(await isHashEqual(token, result.token))) {
        return next(new IncorrectToken('Incorrect token'));
      }
      await AuthService.updateEmailVerified(accountId);
      if (req.isAuthenticated()) {
        req.user.emailVerified = true;
        console.log('verifyEmail: logged in user email verified %o', req.user);
      }
      res.locals.data = true;
      return next();
    } catch (error) {
      return next(error);
    }
  }

从视觉上看,这就是 VSCode 上的错误和 emailVerified 属性的类似错误的样子

有人可以告诉我如何解决这个问题吗?

【问题讨论】:

    标签: typescript express passport.js express-session passport-local


    【解决方案1】:

    如果您将import * as express from 'express'; 添加到您自己的类型声明文件的顶部,它是否有效?

    我发现这可行,但似乎不稳定。当我添加它时,一切都会编译并且 VS Code 没有显示错误。但是我可以再次删除它,它似乎仍然可以工作,即使我运行tsc --build --clean,尽管 VS Code 显示错误。

    【讨论】:

      猜你喜欢
      • 2019-06-23
      • 1970-01-01
      • 1970-01-01
      • 2016-10-19
      • 2014-09-25
      • 2014-03-29
      • 2017-08-18
      • 1970-01-01
      • 2016-10-27
      相关资源
      最近更新 更多