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
相关产品推荐
相关产品推荐

