在 TypeScript 中调用 passport.serializeUser 时如何键入提示用户参数?

How do I type hint the user argument when calling passport.serializeUser in TypeScript?

使用 TypeScript,我正在使用 Express 和 Mongoose 编写 API,并且我正在尝试使用 Passport 设置身份验证,但我收到“属性 不存在” " 尝试将序列化程序函数传递给护照时出错。

根据 documentation,我需要使用一个函数调用 passport.serializeUser,该函数获取我的用户对象并使用该用户的 ID 调用 done

我从 @types/passport 获取类型定义,declaration fileserializeUser 函数的 user 参数键入为 Express.User

serializeUser<TID>(fn: (user: Express.User, done: (err: any, id?: TID) => void) => void): void;

但是 Express.User - 也由 @types/passport 定义 - 是一个空接口:

declare global {
    namespace Express {
        // tslint:disable-next-line:no-empty-interface
        interface AuthInfo {}
        // tslint:disable-next-line:no-empty-interface
        interface User {}

这是我的序列化程序。 TypeScript 抱怨 Property '_id' does not exist on type 'User'.

passport.serializeUser((user, done) => {
  done(null, user._id);
});

为了解决这个问题,我添加了我的类型定义,将 _id 属性 添加到 Express.User:

declare namespace Express {
  interface User {
    _id?: string;
  }
}

这消除了 TypeScript 错误,但这似乎不是解决问题的正确方法。有没有不同的方法来提供不需要我覆盖 Express.User 类型定义的序列化程序函数?

@types/express 贡献者推荐了您Declaration Merging 所做的方式。 您可以找到他们如何使用 TypeScript here.

测试 serializerUser
declare global {
  namespace Express {
    interface User {
      username: string;
      _id?: number;
    }
  }
}

另一种方法是每次使用回调函数时输入 User 参数:

type User = {
  _id?: number
}

passport.serializeUser((user: User, done) => {
  done(null, user._id);
});

我认为声明合并是一种更聪明的方式。