typescript “(e: CustomEvent) => void”类型的参数不可分配给“EventListenerOrEventListenerObject”类型的参数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/47166369/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Argument of type '(e: CustomEvent) => void' is not assignable to parameter of type 'EventListenerOrEventListenerObject'
提问by Get Off My Lawn
I have this custom event setup, and it works with TypeScript 2.5.3
, but when I updated to 2.6.1
I get an error
我有这个自定义事件设置,它适用于 TypeScript 2.5.3
,但是当我更新到2.6.1
我收到一个错误
window.addEventListener('OnRewards', (e: CustomEvent) => {
// my code here
})
[ts] Argument of type '(e: CustomEvent) => void' is not assignable to parameter of type 'EventListenerOrEventListenerObject'.
Type '(e: CustomEvent) => void' is not assignable to type 'EventListenerObject'.
Property 'handleEvent' is missing in type '(e: CustomEvent) => void'.
[ts] '(e: CustomEvent) => void' 类型的参数不可分配给 'EventListenerOrEventListenerObject' 类型的参数。
类型 '(e: CustomEvent) => void' 不能分配给类型 'EventListenerObject'。
类型 '(e: CustomEvent) => void' 中缺少属性 'handleEvent'。
I am not exactly sure what to do here to fix this.
我不确定在这里做什么来解决这个问题。
回答by jcalz
This is due to the behavior of the --strictFunctionTypes
compiler flag added in TypeScript v2.6. A function of type (e: CustomEvent) => void
is no longer considered to be a valid instance of EventListener
, which takes an Event
parameter, not a CustomEvent
.
这是由于--strictFunctionTypes
TypeScript v2.6 中添加的编译器标志的行为。类型的函数(e: CustomEvent) => void
不再被视为 的有效实例EventListener
,它接受一个Event
参数,而不是一个CustomEvent
。
So one way to fix it is to turn off --strictFunctionTypes
.
因此,修复它的一种方法是关闭--strictFunctionTypes
.
Another way is to pass in a function that takes an Event
and then narrows to CustomEvent
via a type guard:
另一种方法是传入一个函数,该函数接受 anEvent
然后CustomEvent
通过类型保护缩小为:
function isCustomEvent(event: Event): event is CustomEvent {
return 'detail' in event;
}
window.addEventListener('OnRewards', (e: Event) => {
if (!isCustomEvent(e))
throw new Error('not a custom event');
// e is now narrowed to CustomEvent ...
// my code here
})
A third way is to use the other overload of addEventListener()
:
第三种方法是使用 的其他重载addEventListener()
:
addEventListener<K extends keyof WindowEventMap>(type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, useCapture?: boolean): void;
If the type
parameter is the name of a known event type (K extends keyof WindowEventMap
) like "onclick"
, then the listener
function will expect its parameter to be of that narrowed event type (WindowEventMap[K]
). The problem is that "OnRewards"
is not a known event type... unless you use declaration mergingto makeit known:
如果type
参数是已知事件类型 ( K extends keyof WindowEventMap
)的名称,例如"onclick"
,则该listener
函数将期望其参数属于该缩小的事件类型 ( WindowEventMap[K]
)。问题是这"OnRewards"
不是已知的事件类型……除非您使用声明合并来使其为人所知:
// merge into WindowEventMap
interface WindowEventMap {
OnRewards: CustomEvent
}
Or, if you're inside a module (anything with export
in it), use global augmentation:
或者,如果您在模块内(其中包含任何export
内容),请使用全局增强:
// merge into WindowEventMap
declare global {
interface WindowEventMap {
OnRewards: CustomEvent
}
}
Then use your code as before:
然后像以前一样使用您的代码:
// no error!
window.addEventListener('OnRewards', (e: CustomEvent) => {
// my code here
})
So, those are your options. Which one you want to choose is up to you. Hope that helps; good luck!
所以,这些是你的选择。你想选择哪一个取决于你。希望有所帮助;祝你好运!
回答by JacobEvelyn
Building off of jcalz's excellent answer, you can also use a type assertionto be a little cleaner:
基于jcalz 的优秀答案,您还可以使用类型断言来更简洁:
window.addEventListener('OnRewards', (e: Event) => {
const detail = (<CustomEvent>e).detail;
...
});
回答by Frederik Krautwald
You also have this option:
你也有这个选项:
window.addEventListener('OnRewards', (e: CustomEvent) => {
// your code here
} as (e: Event) => void)
回答by Stephen Paul
I created a generic function based off @jcalz's answer
我根据@jcalz 的回答创建了一个通用函数
/**
* Checks whether an object can be safely cast to its child type
* @param parent the object to be 'narrowly' cast down to its child type
* @param checkForProps props which aught to be present on the child type
*/
export function isSubTypeWithProps<P, C extends P>(parent: P, ...checkForProps: (keyof C)[]): parent is C {
return checkForProps.every(prop => prop in parent);
}
/**
* Usage example
*/
const el = document.getElementById('test');
el.addEventListener('click', (e: Event) => {
if (isSubTypeWithProps<Event, MouseEvent>(e, 'which')) {
if (e.which === 1) { // primary mouse button only ('which' prop is only available on MouseEvent)
console.log('clicked');
}
}
});