如何在 Typescript 中处理 eventListeners 上的“Event”类型和“CustomEvent”类型

The*_*ris 9 javascript events typescript reactjs

我正在我的应用程序中调度一个CustomEvent带有detail属性的属性,然后我使用事件监听器将其抓取到另一个应用程序中。

我正在努力使用打字稿以使其顺利工作,但无论我到目前为止尝试过什么,我都遇到了障碍。

所以事件监听器就像这样(所有事情都发生在反应全局组件中):

window.addEventListener('my-custom-event', this.callEvent);
Run Code Online (Sandbox Code Playgroud)

再往下,我有callEvent这样的方法:

  callEvent: any = (e: CustomEvent) => {
const {
  detail,
} = e;

.......
}
Run Code Online (Sandbox Code Playgroud)

any当我尝试将函数的类型更改为有意义的类型时,会发生所有长错误“Typescript”消息callEvent,例如:

版本1:

callEvent: (e: CustomEvent) => void = (e: CustomEvent) => {...}
Run Code Online (Sandbox Code Playgroud)

版本 2: .

callEvent(e: CustomEvent) {
const {
  detail,
} = e;

.....
}
Run Code Online (Sandbox Code Playgroud)

分辨率:

No overload matches this call.
Overload 1 of 2, '(type: keyof WindowEventMap, listener: (this: Window, ev: Event | 
UIEvent | BeforeUnloadEvent | FocusEvent | MouseEvent | ... 21 more ... | 
PromiseRejectionEvent) => any, options?: boolean | ... 1 more ... | undefined): 
 void', gave the following error.
Argument of type '"my-custom-event"' is not assignable to parameter of type 
'keyof WindowEventMap'.
 Overload 2 of 2, '(type: string, listener: EventListenerOrEventListenerObject, 
 options?: boolean | AddEventListenerOptions | undefined): void', gave the following 
 error.
 Argument of type '(e: CustomEvent<any>) => void' is not assignable to parameter of 
 type 'EventListenerOrEventListenerObject'.
  Type '(e: CustomEvent<any>) => void' is not assignable to type 'EventListener'.
    Types of parameters 'e' and 'evt' are incompatible.
      Type 'Event' is missing the following properties from type 'CustomEvent<any>': 
 detail, initCustomEvent
Run Code Online (Sandbox Code Playgroud)

版本3:

callEvent: (e: Event) => void = (e: Event) => {
const detail = (<CustomEvent>e).detail; // it thinks this is JSX
...
}
Run Code Online (Sandbox Code Playgroud)

解析: .

var CustomEvent: {
new <T>(typeArg: string, eventInitDict?: CustomEventInit<T> | undefined): 
 CustomEvent<T>;
prototype: CustomEvent<any>;
}
JSX element 'CustomEvent' has no corresponding closing tag.ts(17008)
'React' refers to a UMD global, but the current file is a module. Consider adding an 
import instead.ts(2686)
'CustomEvent' cannot be used as a JSX component.
Its instance type 'CustomEvent<unknown>' is not a valid JSX element.
Type 'CustomEvent<unknown>' is missing the following properties from type 
'ElementClass': render, context, setState, forceUpdate, and 3 more.
Run Code Online (Sandbox Code Playgroud)

还有一些其他版本但都是徒劳的。如果你们知道我能够成功地更换 callEvent: any为合适的类型,请大声喊叫。

如果有任何插件或其他编辑器可以识别和建议,也会很有帮助types。谢谢。

Kel*_*ofs 12

这是因为 TypeScript 不知道您的自定义事件存在。

第一个重载基本上表示它希望您的事件成为 的一部分keyof WindowEventMap,您可以通过增强 WindowEventMap来实现:

declare global {
    interface WindowEventMap {
        'my-custom-event': CustomEvent;
    }
}

// Won't error anymore (unless you misspell your event, of course)
window.addEventListener('my-custom-event', (event: CustomEvent) => {
    
});
Run Code Online (Sandbox Code Playgroud)

第二个重载提到如果你不扩充WindowEventMap,你的参数需要扩展Event

class MyCustomEvent extends Event {}

// No error either, even though 'my-other-custom-event' is completely new
window.addEventListener('my-other-custom-event', (event: MyCustomEvent) => {
    
});
Run Code Online (Sandbox Code Playgroud)


The*_*ris 3

好的,它通过在 eventListener 上添加类型转换来工作,我将其分享给遇到类似情况的任何人。

所以as (e: Event) => void在最后添加如下:

window.addEventListener('my-custom-event', this.callEvent as (e: Event) => void);
Run Code Online (Sandbox Code Playgroud)