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

如何扩展IncomingMessage类型的Request并完整克隆请求对象

问题描述

尝试为Request添加body属性,编写了以下代码,但运行时提示新对象extRequest缺失request的19个方法,请问如何完整克隆request对象?

import { IncomingMessage, ServerResponse } from "http";

interface IRequest extends IncomingMessage {
  body: string;
}
export default (request: IncomingMessage, response: ServerResponse, next: (req: IncomingMessage, res: ServerResponse) => void) => {
    let data: Uint8Array[] = []
    request.on("data", dataChunk => {
        data.push(dataChunk)
    })
    request.on("end", () => {
        const body = Buffer.concat(data).toString();
        if (request.headers["content-type"] === "application/json"){
          const extRequest: IRequest = {...request};
          extRequest.body = body;
          next(extRequest, response)
        }
    })
    request.on("error", () => {
      response.statusCode = 500;
      response.write(`body isn't correct`);
      response.end();
    })
}
原因分析

IncomingMessage是Node.js提供的类实例,它的方法都定义在原型链上。使用扩展运算符{...request}只能复制对象自身的可枚举属性,原型链上的方法不会被拷贝,所以新创建的extRequest会缺失这些方法。

解决方案

方案1:直接类型断言(推荐)

不需要克隆对象,直接对原request进行类型断言,添加body属性即可。JavaScript中对象是动态的,TypeScript只需类型断言就能绕过类型检查:

import { IncomingMessage, ServerResponse } from "http";

interface IRequest extends IncomingMessage {
  body: string;
}
export default (request: IncomingMessage, response: ServerResponse, next: (req: IncomingMessage, res: ServerResponse) => void) => {
    let data: Uint8Array[] = []
    request.on("data", dataChunk => {
        data.push(dataChunk)
    })
    request.on("end", () => {
        const body = Buffer.concat(data).toString();
        if (request.headers["content-type"] === "application/json"){
          // 类型断言为自定义的IRequest
          const extRequest = request as IRequest;
          extRequest.body = body;
          next(extRequest, response)
        }
    })
    request.on("error", () => {
      response.statusCode = 500;
      response.write(`body isn't correct`);
      response.end();
    })
}

方案2:完整克隆实例(不推荐)

如果确实需要创建新实例,可通过Object.create继承原对象的原型,再用Object.assign复制自身属性:

// 在end事件回调中替换克隆逻辑
const extRequest = Object.create(Object.getPrototypeOf(request)) as IRequest;
Object.assign(extRequest, request);
extRequest.body = body;
next(extRequest, response);

注意:克隆IncomingMessage实例可能会导致原对象的事件监听、流状态等出现异常,除非有特殊需求,否则优先使用方案1。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 16:44:53