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
相关产品推荐
相关产品推荐

