You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript中扩展Express.Request添加user属性失败的问题

问题

在TypeScript环境下的Express认证中间件中,尝试给express.Request对象添加user属性时,遇到TypeScript类型错误:

TSError: ⨯ Unable to compile TypeScript:
middlewares/isLoggedIn.ts:72:29 - error TS2339: Property 'user' does not exist on type 'Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>'.

72 request.user = user;
~~~~

已尝试常规扩展Express Request对象的方案但未解决,中间件代码如下:

export const isLoggedInMiddleware = (request:express.Request, response:express.Response, next:express.NextFunction) => {

    
    const token:string|undefined = request.headers.authorization;

    if( !token ){

        Logger.error(`Pas de token !`);
        return response.status(HttpStatusCode.UNAUTHORISED).json({
            
            error: ` Vous n'êtes pas autorisez à accéder à cette resource !`
        });
    }

    const RSA_KEY_PRIVATE:string|undefined = process.env.RSA_KEY_PRIVATE;

    if( !RSA_KEY_PRIVATE ){
            
        throw new APIError(
            'INTERNAL SERVER',
            HttpStatusCode.INTERNAL_SERVER,
            `La key public n'existe pas`,
            true
        );
    }

    jsonwebtoken.verify(token, RSA_KEY_PRIVATE.replace('/\n/g', '\n'), (error, decoded) => {

        if(error) {
            
            Logger.error("Token invalid")
            return response.status(HttpStatusCode.UNAUTHORISED).json({
                
                error: 'Token invalid'
            });
        }

        const sub:any= decoded?.sub;

        try {
            
            userService.getUserById(sub).then( (user:User|null) => {
                
                if(user){

                    request.user = user;
                } else {

                    Logger.error("Le user n existe pas");
                    response.status(HttpStatusCode.UNAUTHORISED).json({

                        error: 'Vous n\'etes pas autorisé'
                    });
                }

            })
        } catch (error) {
            
            Logger.error("Une erreur rencontré lors de la récuperation du user");
            return response.status(HttpStatusCode.UNAUTHORISED).json({
                'error':error
            });
        }
    });

    next();
}   

解决方案

1. 正确扩展Express Request类型

创建类型声明文件,比如在项目src/types目录下新建express.d.ts,内容如下:

import { User } from '../path/to/your/user/model'; // 替换成你的User类型实际路径

declare module 'express-serve-static-core' {
  interface Request {
    user?: User; // 根据业务需求设置为可选或必选
  }
}

检查tsconfig.json配置,确保类型文件被正确识别:

{
  "compilerOptions": {
    // 其他配置保持不变
    "typeRoots": ["./node_modules/@types", "./src/types"]
  },
  "include": [
    "src/**/*",
    "src/types/**/*"
  ]
}

注意:必须在express-serve-static-core模块下声明扩展,因为Express的Request接口实际来自这个包,而非express本身。

2. 修复异步逻辑错误

你的代码存在严重的异步逻辑问题:next()在异步操作(jsonwebtoken.verify和getUserById)外直接调用,会导致后续中间件执行时request.user还未被赋值。修改后的代码如下:

export const isLoggedInMiddleware = (request: express.Request, response: express.Response, next: express.NextFunction) => {
  const token = request.headers.authorization;

  if (!token) {
    Logger.error(`Pas de token !`);
    return response.status(HttpStatusCode.UNAUTHORISED).json({
      error: ` Vous n'êtes pas autorisez à accéder à cette resource !`
    });
  }

  const RSA_KEY_PRIVATE = process.env.RSA_KEY_PRIVATE;

  if (!RSA_KEY_PRIVATE) {
    throw new APIError(
      'INTERNAL SERVER',
      HttpStatusCode.INTERNAL_SERVER,
      `La key public n'existe pas`,
      true
    );
  }

  // 修复正则表达式:替换转义的\n为实际换行符
  jsonwebtoken.verify(token, RSA_KEY_PRIVATE.replace(/\\n/g, '\n'), (error, decoded) => {
    if (error) {
      Logger.error("Token invalid");
      return response.status(HttpStatusCode.UNAUTHORISED).json({
        error: 'Token invalid'
      });
    }

    const sub = decoded?.sub;
    if (!sub) {
      Logger.error("Token sub missing");
      return response.status(HttpStatusCode.UNAUTHORISED).json({
        error: 'Token invalide'
      });
    }

    userService.getUserById(sub)
      .then((user: User | null) => {
        if (user) {
          request.user = user;
          next(); // 成功获取用户后再调用next,传递给后续中间件
        } else {
          Logger.error("Le user n'existe pas");
          response.status(HttpStatusCode.UNAUTHORISED).json({
            error: 'Vous n\'êtes pas autorisé'
          });
        }
      })
      .catch((error) => {
        Logger.error("Une erreur rencontrée lors de la récupération du user");
        response.status(HttpStatusCode.UNAUTHORISED).json({
          error: error
        });
      });
  });
}

内容的提问来源于stack exchange,提问作者Sodiki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 03:35:42