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

TypeScript如何扩展lib.dom.d.ts声明的全局Response变量?

问题描述

我正在实现Response.json静态方法的polyfill。Response构造函数(即类本身,不是实例接口)的类型声明在TS内置的lib.dom.d.ts文件中。
如果Response是通过具名构造函数接口声明的,形式如下:

declare var Response: ResponseConstructor;

interface ResponseConstructor {
  prototype: Response;
  new (body?: BodyInit | null, init?: ResponseInit): Response;
  error(): Response;
  redirect(url: string | URL, status?: number): Response;
};

那直接通过接口合并就能很方便地扩展类型,在自己的d.ts文件里写如下代码即可:

declare global {
  interface ResponseConstructor {
    json(data: any, init?: ResponseInit): Response;
  };
}

但实际内置的Response是直接给全局变量赋值匿名类型的形式声明,没有暴露可扩展的具名构造函数接口:

declare var Response: {
  prototype: Response;
  new (body?: BodyInit | null, init?: ResponseInit): Response;
  error(): Response;
  redirect(url: string | URL, status?: number): Response;
};

这时候如果直接重复声明全局Response变量,仅写新增的json方法:

declare global {
  var Response: {
    json(data: any, init?: ResponseInit): Response;
  };
}

会抛出如下类型错误:

Subsequent variable declarations must have the same type.  Variable 'Response' must be of type '{ new (body?: BodyInit | null | undefined, init?: ResponseInit | undefined): Response; prototype: Response; error(): Response; redirect(url: string | URL, status?: number | undefined): Response; }', but here has type '{ json(data: any, init?: ResponseInit | undefined): Response; }'.
解决方案

有两种兼容性较好的写法可以实现类型扩展,代码放在项目中任意被TS识别的全局.d.ts文件中即可生效。

  • 写法1(兼容性最佳,推荐):手动补全完整的构造函数接口,覆盖全局Response的类型
declare global {
  interface ResponseConstructor {
    prototype: Response;
    new (body?: BodyInit | null, init?: ResponseInit): Response;
    error(): Response;
    redirect(url: string | URL, status?: number): Response;
    // 新增的json静态方法
    json(data: unknown, init?: ResponseInit): Response;
  }
  var Response: ResponseConstructor;
}

这种写法只要保证原有属性、方法、构造签名的类型和内置定义完全一致,仅新增需要的json方法,就不会触发类型冲突,全版本TS都能正常识别。

  • 写法2(代码更简洁,适合较新版本TS):用工具类型交叉合并原有类型和新增方法
declare global {
  var Response: typeof globalThis.Response & {
    json(data: unknown, init?: ResponseInit): Response;
  }
}

这里用typeof globalThis.Response取内置的原始Response类型,避免直接写typeof Response出现循环引用问题,再通过交叉类型把新增的json方法合并进去,不需要手动复制所有原有类型签名。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 03:24:32