提问者:小点点

TypeScript:req.user可能是'undefined'-express和passport js


我有一个使用Passport工作的Nodejs typescript身份验证系统。

我的问题是,当我在路由中使用req.user时,我在req.user上遇到以下错误:对象可能是“undefined”。

这是Typescript的正常行为,但我正在使用中间件来保护要在其中使用req.user的路由,这样就不能取消定义req.user

这是我扩展express.user类型的地方:

import { users } from "@prisma/client";

declare global {
    namespace Express {
        interface User extends users {}
    }
}

这是我用来保护已登录用户的路由的中间件:

export function checkIsAuthenticated(req: Request, res: Response, next: NextFunction) {
    if (req.isAuthenticated()) {
        if (!req.user) req.logOut();
        else return next();
    }
    res.status(400).json({
        errors: [{ message: "no user logged in" }],
    });
}

这是获取用户信息的路径:

export function userRoute(req: Request, res: Response) { // defining the route
    res.json({
        id: req.user.id,               // I'm getting the error in these 4 lines
        username: req.user.username,   //
        email: req.user.email,         //
        role: req.user.role,           //
    });
}

router.get("/user", checkIsAuthenticated, userRoute); // using the route

我不想检查是否定义了user,因为我不想在每条路由中都这样做,这不是一个好的做法。这就是中间件的原因。

我不擅长打字,所以我需要一些帮助来修理它。谢谢


共2个答案

匿名用户

null

export function userRoute(req: Request, res: Response) { // defining the route
    res.json({
        id: req.user!.id,               // you tell typescript that req.user for sure not. null
        username: req.user!.username,   //
        email: req.user!.email,         //
        role: req.user!.role,           //
    });
}

router.get("/user", checkIsAuthenticated, userRoute);

匿名用户

我不想检查是否定义了user,因为我不想在每条路由中都这样做,这不是一个好的做法。

我的第一个解决方案试图适应这个需求,但没有工作,所以我删除了它。我留下了我的第二个解决方案,它是:

但是,我要反驳的是,如果您在一条忘记进行身份验证的路由上意外地使用了这些处理程序之一,那么检查用户的请求并给自己一条很好的、有用的错误消息并没有什么错。这看起来应该是这样的:

type RequestWithUser = Request & {user: typeOfUserObject};
function assertHasUser(req: Request): asserts req is RequestWithUser {
    if (!( "user" in req)) {
        throw new Error("Request object without user found unexpectedly");
    }
}

则这些路由的处理程序:

export function userRoute(req: Request, res: Response) {
    assertHasUser(req);
    // ...you can use `req.user` here...
});

操场示例

(您实际上并不需要显式的RequestWithUser类型,您可以只使用Asserts req is Request&{user:typeOfUserObject}。)