машинопись: req.пользователь, возможно, «не определен» — экспресс и паспорт js

#node.js #typescript #express #passport.js

Вопрос:

У меня есть система аутентификации на основе машинописного текста Nodejs, которая работает с использованием паспорта.

Моя проблема в том, что когда я использую req.user маршрут, я получаю эту ошибку req.user : Object is possibly '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
 

Я не хочу проверять, определен ли пользователь, потому что я не хочу делать это на каждом маршруте, и это не очень хорошая практика. Вот почему промежуточное программное обеспечение предназначено для.

Я плохо разбираюсь в машинописи, поэтому мне нужна помощь, чтобы это исправить. Спасибо

Комментарии:

1. «Я не хочу проверять, определен ли пользователь, потому что я не хочу делать это на каждом маршруте, и это не очень хорошая практика». Я бы не сказал, что это плохая практика. Это дало бы вам хорошую явную ошибку, если бы вы, например, пропустили промежуточное программное обеспечение аутентификации при создании одного из этих маршрутов.

Ответ №1:

Я не хочу проверять, определен ли пользователь, потому что я не хочу делать это на каждом маршруте, и это не очень хорошая практика.

Мое первое решение, пытающееся удовлетворить это требование, не сработало, поэтому я удалил его. Я оставил свое второе решение, которое заключается в:

Но я бы сказал, что нет ничего плохого в том, чтобы проверить запрос пользователя и выдать себе приятное полезное сообщение об ошибке, если вы случайно использовали один из этих обработчиков на маршруте, на котором вы забыли установить аутентификацию. Это выглядело бы так:

 type RequestWithUser = Request amp; {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 amp; {user: typeOfUserObject} .)

Комментарии:

1. Большое вам спасибо за вашу помощь! Было бы здорово, если бы express мог обнаружить, что я проверяю свойство запроса в промежуточном программном обеспечении для запроса, но я думаю, что в настоящее время это ограничение JS или TS, и мы должны пока обойти его.

Ответ №2:

 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); 

Комментарии:

1. Это сработает, но лучше всего избегать подобных утверждений.