【问题标题】:Typescript is not recognising the type of user from express-session打字稿无法识别快速会话中的用户类型
【发布时间】:2021-11-13 12:02:58
【问题描述】:

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

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&lt;User&gt;,因为我使用Typegoose 键入我的模型。我不确定这是否是 Typegoose 的做法。

我做错了什么?任何意见将不胜感激。

【问题讨论】:

    标签: typescript mongodb express mongoose typegoose


    【解决方案1】:

    问题是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 检索到,而MongoDBStore 不知道User 模型和Typegoose 定义的方法。所以,这就是我们解决这个问题的方法。同样的解决方案也适用于带有 Mongoose 的 Javascript。

    【讨论】:

      猜你喜欢
      • 2023-01-11
      • 1970-01-01
      • 2023-03-26
      • 1970-01-01
      • 1970-01-01
      • 2020-03-24
      • 2019-11-12
      • 2020-04-30
      • 2017-05-20
      相关资源
      最近更新 更多