打字稿无法识别快速会话中的用户类型

Typescript is not recognising the type of user from express-session

我正在从数据库中检索用户对象并将其设置在快速会话中:

export const postLogin = async (
    request: Request,
    response: Response,
    next: NextFunction
): Promise<void> => {
    try {
        request.session.user = await UserModel.findById('6127bd9d204a47128947a07d').orFail().exec()
        response.redirect('/')
    } catch (error) {
        next(error)
    }
}

然后我在用户对象上调用 Mongoose 方法 populate() 以获取与其关联的购物车:

export const getCart = async (
    request: Request,
    response: Response,
    next: NextFunction
): Promise<void> => {
    try {
        const userWithCartProducts = await request.session.user
            .populate('cart.items.productId')
            .execPopulate()
    } catch (error) {
        next(error)
    }
}

但是这里我得到一个错误:TypeError: request.session.user.populate is not a function

我已经在 express-session 上定义了自定义用户类型,如下所示:

declare module 'express-session' {
    interface SessionData {
        user?: DocumentType<User>
    }
}

正如您在上面 user 的定义中看到的,我使用 DocumentType<User> 因为我使用 Typegoose 输入我的模型。我不确定这是否是 Typegoose 的处理方式。

我做错了什么?任何输入将不胜感激。

问题是 session 对象中的 user 对象被 MongoDBStore 提取了。 MongoDBStore 不知道 Typegoose 中定义的 User 模型,因此,当它从会话数据库中获取数据时,它只获取原始数据,而不是 Typegoose 模型中定义的方法.

所以,为了解决这个问题,当一个新的请求进来时,在初始化 express-session 之后,在一个中间件中,我们需要从数据库中获取一次用户并放入 request 对象中如下所示:

app.use(initializeUser)

export const initializeUser = async (request: Request, response: Response, next: NextFunction): Promise<void> => {
    try {
        request.user = await User.findById(request.session.user._id).orFail().exec()
        next()
    } catch (error) {
        next(error)
    }
}

对于 Typegoose,在 Request 上定义 User 模型如下:

declare global {
    declare namespace Express {
        export interface Request {
            user?: DocumentType<User>
        }
    }
}

如问题中所述,在 login 路由中,即使我们将 user 对象存储在 session 中,请求也会在那里终止,会话(以及使用 user 对象)被保存到数据库中。但是下一次 request 进来时, session 中可用的 user 对象被 MongoDBStore 检索,它不知道 User 模型并且Typegoose 定义的方法。所以,这就是我们解决这个问题的方法。同样的解决方案也适用于 Javascript with Mongoose。