使用CustomEvents时遇到TypeScript错误的技术问询
搞定TypeScript里自定义事件的类型报错问题
嘿,我明白你遇到的麻烦了——明明JS代码跑起来没问题,一换成TypeScript就各种类型报错,别慌,这是因为TS对DOM事件的类型校验比JS严格多了,默认只认标准事件,自定义事件得我们手动给它“注册”类型才行。
先解决第一种场景:全局监听自定义事件
你原来的代码在JS里能跑,但TS里访问e.detail报错,是因为TS默认把e推断成了Event类型,而Event根本没有detail属性;当你手动加e: CustomEvent时,又因为"MyCustomEvent"不是标准事件名,所以触发了“No overload matches this call”的错误。
给你两个解决方案:
- 推荐方案:全局扩展事件类型(适合项目里多次用到这个自定义事件的情况)
先在代码里扩展全局的WindowEventMap,把你的自定义事件加进去:// 扩展全局类型,放在项目的.d.ts文件里或者当前文件顶部都行 declare global { interface WindowEventMap { // 把<你的数据类型>换成detail实际的类型,比如<string>、<{id: number}>这类 MyCustomEvent: CustomEvent<你的数据类型>; } } // 现在再写监听就完全没问题了,TS能自动识别e.detail的类型 addEventListener("MyCustomEvent", (e) => { console.log(e.detail); }); - 临时方案:局部类型断言/泛型指定(适合只用一次的场景)
不想全局改的话,直接给事件对象做断言,或者给addEventListener指定泛型:// 类型断言写法 addEventListener("MyCustomEvent", (e) => { console.log((e as CustomEvent).detail); }); // 泛型指定写法 addEventListener<CustomEvent<你的数据类型>>("MyCustomEvent", (e) => { console.log(e.detail); });
再解决第二种场景:类里绑定自定义事件
你这个类的代码报错,原因和第一种一样——TS不认MyCustomEvent这个自定义事件名,导致addEventListener的类型不匹配。
解决方案也很简单:
- 如果你已经用了上面的全局扩展类型,那直接用原来的代码就不会报错了;
- 要是不想全局扩展,就给事件名称加个类型断言:
另外说一句,你用箭头函数定义class Foo { constructor() { // 把事件名称断言成WindowEventMap的键,绕过TS的校验 document.addEventListener("MyCustomEvent" as keyof WindowEventMap, this.Bar); } // 这里记得给CustomEvent加上你实际的detail类型哦 Bar = (e: CustomEvent<你的数据类型>): void => { console.log(e.detail); } }Bar是对的,这样this的指向永远是当前实例,不会出现绑定丢失的问题,这部分不用改~
总的来说,核心就是让TS“认识”你的自定义事件,要么全局注册类型(长远来看更方便),要么局部用断言/泛型临时解决,两种方法都能搞定这些报错。
内容的提问来源于stack exchange,提问作者Tc_
相关产品推荐
相关产品推荐

