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

如何在TypeScript中不使用namespace扩展Express的Request接口?

解决NestJS中扩展Express Request接口(避免namespace)的问题

问题分析

你之前用全局namespace扩展Express的Request接口虽能实现需求,但触发了linter关于"ES2015模块语法优于namespace"的警告,且TypeScript文档确实不推荐用namespace扩展模块类型。直接本地声明Request接口会和从express导入的接口冲突,移除导入又会丢失类型提示,不可取。

正确实现方式

方案1:在中间件文件中使用模块式全局扩展

保留全局声明,但改用TypeScript推荐的模块扩展语法,避免使用namespace:

import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
import { UsersService } from '../users.service';
import { User } from '../user.entity';

// 全局扩展Express的Request接口
declare global {
  interface Express {
    Request: Request & {
      currentUser?: User;
    };
  }
}

@Injectable()
export class CurrentUserMiddleware implements NestMiddleware {
  constructor(private usersService: UsersService) {}
  async use(req: Request, res: Response, next: NextFunction) {
    const { userId } = req.session || {};

    if (userId) {
      const user = await this.usersService.findOne(userId);
      req.currentUser = user; // 此时currentUser已被正确识别类型
    }

    next();
  }
}

方案2:创建独立的类型定义文件(更规范)

在项目中新建类型定义文件(比如src/types/express.d.ts),专门用来扩展Express的类型,这样中间件代码更简洁,也符合TypeScript的模块规范:

  1. 创建src/types/express.d.ts:
// 导入User实体类型
import { User } from '../user.entity';

// 扩展express模块的Request接口
declare module 'express' {
  interface Request {
    currentUser?: User;
  }
}
  1. 修改current-user.middleware.ts,移除原来的全局声明:
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
import { UsersService } from '../users.service';

@Injectable()
export class CurrentUserMiddleware implements NestMiddleware {
  constructor(private usersService: UsersService) {}
  async use(req: Request, res: Response, next: NextFunction) {
    const { userId } = req.session || {};

    if (userId) {
      const user = await this.usersService.findOne(userId);
      req.currentUser = user; // 类型已自动识别
    }

    next();
  }
}

关键说明

  • 方案2更适合大型项目,类型定义集中管理,避免代码冗余。
  • 两种方式都不会触发linter的namespace警告,且能完整保留Request的原有类型提示,同时新增currentUser字段。
  • 不要移除express的Request导入,否则会失去Express请求对象的所有内置类型提示,导致后续开发中类型校验失效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 12:15:29