TypeScript扩展Express Request 如何定义非可选user的鉴权请求类型
报错根因
Express 内置的RequestHandler类型定义中,req参数固定为你全局扩展后的Request类型,其中user是可选属性,而你自定义的AuthenticatedRequest要求user必须存在,二者类型不匹配导致报错。
可行解决方案
方案1:自定义鉴权请求处理函数类型
直接定义适配AuthenticatedRequest的处理函数类型,完全保留类型安全:
import { ParamsDictionary, RequestHandler, Response, NextFunction } from "express-serve-static-core"; import { ParsedQs } from "qs"; // 全局定义的UserData类型 type UserData = Record<string, any>; // 自定义鉴权后的请求处理函数泛型,兼容Express原生泛型参数 type AuthRequestHandler< P = ParamsDictionary, ResBody = any, ReqBody = any, ReqQuery = ParsedQs, Locals extends Record<string, any> = Record<string, any> > = ( req: Omit<Request<P, ResBody, ReqBody, ReqQuery, Locals>, 'user'> & { user: UserData }, res: Response<ResBody, Locals>, next: NextFunction ) => void; // 直接使用自定义类型定义路由处理函数 const handler: AuthRequestHandler = (req, res, next) => { // req.user自动识别为非可选的UserData类型 console.log(req.user.id); };
方案2:用类型守卫自动收窄类型
将鉴权逻辑封装为类型守卫,无需修改处理函数的原生类型定义:
// 你原来的AuthenticatedRequest定义 export interface AuthenticatedRequest extends Omit<Request, 'user'> { user: UserData } // 类型守卫函数,判断请求是否已鉴权 function isAuthReq(req: Request): req is AuthenticatedRequest { return !!req.user; } // 处理函数仍使用原生RequestHandler类型 const handler: RequestHandler = (req, res, next) => { if (!isAuthReq(req)) return res.sendStatus(401); // 经过守卫判断后,TS自动识别req为AuthenticatedRequest类型,user非可选 console.log(req.user.id); };
方案3:类型断言(快速实现用)
如果确定前置鉴权中间件一定会给req.user赋值,可直接用类型断言跳过校验,适合临时快速开发:
const handler: RequestHandler = (req, res, next) => { const user = req.user as UserData; // 后续直接使用user变量即可 };
内容的提问来源于stack exchange,提问作者dor272
相关产品推荐
相关产品推荐

