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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 20:45:03