如何扩展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
相关产品推荐
相关产品推荐

