导出全局声明破坏自定义模块声明,如何实现两者共存?
问题描述
在Next.js Web应用中,我给无类型的已安装包配置了自定义类型声明,同时为了通过第三方脚本扩展window对象,在global.d.ts文件里用export declare global扩展了Window接口。但这么做之后,某个全局声明为any类型的包触发了TS7016错误,删掉那个导出语句后错误就消失了。请问怎么同时保留第三方模块的自定义类型和导出的全局自定义类型?
对应的代码示例:
// global.d.ts declare module '@package-maintainer/*'; declare module '@package-maintainer-2/*'; declare module 'some-package'; declare module 'some-package-2'; export declare global { interface Window { thirdPartyModule: { aMethod: () => void }; } }
解决方案
方案1:拆分类型声明文件
把第三方模块的类型声明和全局Window扩展拆成两个独立文件:
- 新建
modules.d.ts,专门存放模块声明:
// modules.d.ts declare module '@package-maintainer/*'; declare module '@package-maintainer-2/*'; declare module 'some-package'; declare module 'some-package-2';
- 保留
global.d.ts只处理Window扩展,注意不要用export前缀,最后加一行export {}标记文件为模块:
// global.d.ts declare global { interface Window { thirdPartyModule: { aMethod: () => void }; } } // 标记文件为模块,确保全局扩展生效 export {};
方案2:在原文件中调整写法
如果不想拆分文件,直接修改global.d.ts:去掉export declare global里的export,最后添加export {}把文件标记为模块:
// global.d.ts declare module '@package-maintainer/*'; declare module '@package-maintainer-2/*'; declare module 'some-package'; declare module 'some-package-2'; declare global { interface Window { thirdPartyModule: { aMethod: () => void }; } } // 标记为模块,避免全局作用域冲突 export {};
为什么这样能解决问题
当你用export declare global时,整个文件会被TypeScript认定为模块,里面的declare module就变成了模块内部的局部声明,不再是全局生效的类型声明,导致TypeScript无法识别这些包的类型,抛出TS7016错误。通过拆分文件或者调整写法,既能让模块声明保持全局生效,又能正确扩展Window接口,两者互不影响。
内容的提问来源于stack exchange,提问作者Fillip Peyton
相关产品推荐
相关产品推荐

