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

如何为Express的已认证/未认证请求定义TypeScript类型?

解决TypeScript识别Express已认证路由请求类型的方案

方案1:定义已认证专用请求接口 + 类型守卫

首先在全局声明文件中扩展两个接口:一个适配所有路由的基础Request(user可空),另一个是保证user非空的已认证专用接口:

// types/express.d.ts
declare global {
  namespace Express {
    // 基础请求接口,覆盖所有路由场景
    interface Request {
      isAuthenticated: boolean;
      sid?: string;
      locals: {
        user: User | null;
      };
    }

    // 已认证请求专用接口,强制user非null
    interface AuthenticatedRequest extends Request {
      locals: {
        user: User;
      };
    }
  }
}

// 导出空对象让TypeScript识别为模块
export {};

接着编写认证中间件,用类型守卫函数判断请求是否符合已认证状态,未认证直接拦截:

// middleware/auth.ts
import { Request, Response, NextFunction } from 'express';

// 类型守卫:校验请求是否为已认证状态
function isAuthenticated(req: Request): req is Express.AuthenticatedRequest {
  return req.isAuthenticated === true && req.locals.user !== null;
}

// 强制认证中间件
export const requireAuth = (req: Request, res: Response, next: NextFunction) => {
  if (!isAuthenticated(req)) {
    return res.status(401).send('未授权,请先登录');
  }
  // 经过守卫后,后续路由的req会被TypeScript自动推断为AuthenticatedRequest
  next();
};

在路由中使用该中间件后,无需重复判断user是否存在,TypeScript会自动识别user的非空状态:

// routes/profile.ts
import { Router } from 'express';
import { requireAuth } from '../middleware/auth';

const router = Router();

router.get('/me', requireAuth, (req, res) => {
  // TypeScript 自动推断 req 为 AuthenticatedRequest,user 非null
  res.json({
    id: req.locals.user.id,
    username: req.locals.user.username
  });
});

方案2:中间件内直接类型断言(简化版)

如果觉得类型守卫过于繁琐,可在认证中间件里直接用类型断言,但要确保中间件已经拦截了所有未认证请求:

// middleware/auth.ts
export const requireAuth = (req: Request, res: Response, next: NextFunction) => {
  if (!req.isAuthenticated || req.locals.user === null) {
    return res.status(401).send('未授权');
  }
  // 断言为已认证请求类型,后续路由可直接使用
  next();
};

// 路由中使用时,可手动指定类型或让TypeScript自动推断
router.get('/settings', requireAuth, (req: Express.AuthenticatedRequest, res) => {
  res.json({ email: req.locals.user.email });
});

核心思路

  • 基础Request接口保留user | null的宽松类型,适配所有路由场景;
  • 专用的AuthenticatedRequest接口确保user非空,仅用于经过认证中间件的路由;
  • 通过类型守卫或中间件拦截,让TypeScript自动推断请求类型,彻底消除重复的if (user)判断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 19:35:22