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

Express.js Request泛型扩展属性时catchAsync泛型失效问题

解决Express Request类型扩展后catchAsync泛型未正确应用的问题

问题原因分析

你遇到的req.formData.data始终被识别为any而非指定的IPostProduct,主要有几个核心原因:

  1. 类型扩展文件index.d.ts未被TypeScript正确识别,导致自定义的formData属性类型不生效;
  2. middleware.ts中未正确导入qs模块,导致qs.ParsedQs类型失效,干扰泛型推断;
  3. 原catchAsync未捕获异步错误(虽不直接影响类型,但会导致Express无法处理异步异常)。

解决方案

1. 确保类型扩展文件被TypeScript识别

检查tsconfig.json的include配置,将index.d.ts加入编译包含范围,同时开启严格模式提升类型推断准确性:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*", "./index.d.ts"]
}

2. 修复middleware.ts的依赖导入与错误捕获逻辑

补充qs模块导入,并完善catchAsync的错误捕获(否则异步抛出的错误无法被Express错误中间件处理):

import { Request, Response, NextFunction } from 'express';
import * as qs from 'qs'; // 导入qs模块

export type AsyncRequestHandler<M> = (
  req: Request<any, any, M, qs.ParsedQs, Record<string, any>>,
  res: Response,
  next: NextFunction,
) => Promise<void>;

export const catchAsync =
  <M = any>(fn: AsyncRequestHandler<M>): AsyncRequestHandler<M> =>
  async (req, res, next) => {
    try {
      await fn(req, res, next);
      if (!res.headersSent) {
        next();
      }
    } catch (err) {
      next(err); // 将异步错误传递给Express错误处理中间件
    }
  };

3. 正确约束泛型类型

有两种方式可以让data类型正确推断为IPostProduct:

方式一:手动指定泛型参数

postProduct = catchAsync<IPostProduct>(async (req, res) => {
  // 先校验formData存在性,避免解构undefined
  if (!req.formData) {
    throw new Error('表单数据未解析');
  }
  const { data } = req.formData; // 此时data类型为IPostProduct
  await ProductController._productService.create(data);
  res.status(201).send();
});

方式二:显式标注req类型(推荐,无需手动传递泛型)

postProduct = catchAsync(async (req: Request<any, any, IPostProduct>, res) => {
  if (!req.formData) {
    throw new Error('表单数据未解析');
  }
  const { data } = req.formData; // data类型自动推断为IPostProduct
  await ProductController._productService.create(data);
  res.status(201).send();
});

验证类型生效

完成上述配置后重新编译项目,req.formData.data将被正确识别为IPostProduct类型,而非any。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 14:15:36