TypeScript中正确使用浏览器专属属性:Firefox Error的fileName问题
问题描述
我想在Firefox中使用Error对象的fileName等专属属性,但直接编写代码时该属性会出现红色下划线。尝试通过声明合并扩展Error接口,未导出函数时可消除下划线,但导出函数后下划线再次出现。此外,将参数e重新赋值给自己会让类型变为any从而消除错误,目前暂时使用// @ts-ignore规避,想了解声明合并失效的原因及正确解决方法。
相关代码示例
未扩展接口时
function normalizeError(e:Error|ErrorEvent|PromiseRejectionEvent|any) { if(e instanceof Error){ return { line: e?.fileName //有下划线 } }else return null }
声明合并未导出函数时
interface Error { fileName?: string } function normalizeError(e:Error|ErrorEvent|PromiseRejectionEvent|any) { if(e instanceof Error){ return { line: e?.fileName //无下划线 } }else return null }
导出函数后
interface Error { fileName?: string } // Exported now: export function normalizeError(e:Error|ErrorEvent|PromiseRejectionEvent|any) { if(e instanceof Error){ return { line: e?.fileName //下划线再次出现 } }else return null }
原因分析
当你导出函数时,当前文件会变成一个模块,不再是全局脚本。在模块作用域内,直接声明的interface Error只会覆盖当前模块内的Error类型,不会和全局的Error接口合并。而未导出函数时,文件属于全局脚本,声明的接口会自动合并到全局Error类型中,因此能正常识别fileName属性。
正确解决方法
方法1:扩展全局Error接口(推荐)
在模块中扩展全局类型,需要将声明放在global命名空间下,这样就能和全局的Error接口合并:
declare global { interface Error { fileName?: string; // 可按需添加其他Firefox专属属性,比如lineNumber lineNumber?: number; } } export function normalizeError(e:Error|ErrorEvent|PromiseRejectionEvent|any) { if(e instanceof Error){ return { line: e?.fileName // 无红色下划线 } }else return null }
这种方式会让所有地方的Error类型都包含扩展的属性,适合全局需要使用这些属性的场景。
方法2:自定义类型+类型断言
如果不想修改全局类型,可以创建包含Firefox专属属性的自定义接口,在类型判断后进行断言:
interface FirefoxError extends Error { fileName?: string; lineNumber?: number; } export function normalizeError(e:Error|ErrorEvent|PromiseRejectionEvent|any) { if(e instanceof Error){ const firefoxErr = e as FirefoxError; return { line: firefoxErr?.fileName } }else return null }
这种方式仅在当前函数内生效,不会影响全局类型,适合局部使用的场景。
内容的提问来源于stack exchange,提问作者ADJenks
相关产品推荐
相关产品推荐

