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

如何在Express与TypeScript项目中正确实现上下文共享

疑问1:是否是Express规范实现

你当前的写法本身就是Express生态下的通用规范实现。Express官方没有提供专属的上下文注入API,官方文档和示例中也大量使用「将请求生命周期内的共享数据挂载到req对象」的方案,比如用户鉴权信息、数据库连接实例、配置项等都会通过中间件挂载到req上。
这种方案天然满足可mock的要求:单元测试时既可以直接给中间件传入mock的RequestContext实例,也可以在单独测试路由处理函数时,直接构造带mockcontext字段的req对象传入,不需要额外的适配逻辑。

疑问2:是否存在不修改req/res的实现方案

有两类可行方案,但整体复杂度比挂载req更高,适合有特定架构要求的项目:

  • 依赖注入(DI)方案:引入DI容器搭配适配的Express路由库,将上下文注册为请求作用域的依赖,路由处理函数通过构造函数注入或者参数装饰器获取上下文,完全不需要触碰req/res对象。缺点是需要引入整套DI框架,小项目使用过重。
  • 高阶路由包装方案:封装路由处理函数的生成方法,把上下文作为独立参数传入处理函数,示例代码如下:
// 路由包装函数
const withContext = (handler: (req: Request, res: Response, ctx: RequestContext) => void) => {
  const context = { foo: 'bar' } // 或者从其他全局/请求级位置生成
  return (req: Request, res: Response) => handler(req, res, context)
}

// 使用
const mainRoute = express.Router().get('/test', withContext((req, res, context) => {
  res.json({ context })
}))

该方案的缺点是如果上下文是请求级动态生成的(比如包含当前请求的用户信息),还是需要额外从req中取参数生成上下文,并没有减少工作量。

疑问3:是否有更优的类型处理方案

可以通过TypeScript的模块扩展特性,直接扩展Express原生的Request接口类型,不需要每次手动写交叉类型,操作步骤如下:

  1. 在项目中新建类型声明文件,比如src/types/express.d.ts
  2. 写入以下内容:
import type { RequestContext } from '../你的上下文类型文件路径'

declare global {
  namespace Express {
    interface Request {
      // 如果所有请求都保证走中间件,就写必选属性,否则写可选属性
      context: RequestContext
    }
  }
}

配置完成后,项目中所有的ExpressRequest对象默认会带上context字段的类型提示,不需要再手动声明Request & HasContext。


内容的提问来源于stack exchange,提问作者Balázs Édes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 21:36:04