'(e:CustomEvent)=>类型的参数void'不能赋值给'EventListenerOrEventListenerObject'类型的参数

时间:2017-11-07 19:53:49

标签: javascript typescript

我有自定义事件设置,它适用于TypeScript 2.5.3,但当我更新到2.6.1时出现错误

window.addEventListener('OnRewards', (e: CustomEvent) => {
    // my code here
})
  

[TS]   '(e:CustomEvent)=>类型的参数void'不能赋值给'EventListenerOrEventListenerObject'类型的参数。

     

输入'(e:CustomEvent)=> void'不能赋值为'EventListenerObject'。

     

类型'(e:CustomEvent)=>中缺少属性'handleEvent'无效”。

我不确定该怎么做才能解决这个问题。

4 个答案:

答案 0 :(得分:12)

这是由于TypeScript v2.6中添加了--strictFunctionTypes编译器标志的行为。类型(e: CustomEvent) => void的函数不再被视为EventListener的有效实例,它采用Event参数,而不是CustomEvent

因此,解决此问题的一种方法是关闭--strictFunctionTypes

另一种方法是传入一个带Event的函数,然后通过一个类型后卫缩小到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 
})

第三种方法是使用addEventListener()的其他重载:

addEventListener<K extends keyof WindowEventMap>(type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, useCapture?: boolean): void;

如果type参数是已知事件类型(K extends keyof WindowEventMap)的名称,例如"onclick",那么listener函数将期望其参数变窄事件类型(WindowEventMap[K])。问题是"OnRewards"不是已知的事件类型...除非您使用declaration merging 使知道它:

// merge into WindowEventMap
interface WindowEventMap {
    OnRewards: CustomEvent
}

或者,如果您在模块内(其中包含export的任何内容),请使用global augmentation

// merge into WindowEventMap
declare global {
  interface WindowEventMap {
    OnRewards: CustomEvent
  }
}

然后像以前一样使用您的代码:

// no error!
window.addEventListener('OnRewards', (e: CustomEvent) => {
    // my code here
})

所以,这些是你的选择。您要选择哪一个取决于您。希望有所帮助;祝你好运!

答案 1 :(得分:4)

建立jcalz's excellent answer,您还可以使用type assertion更清洁:

bitmap

答案 2 :(得分:1)

你也有这个选择:

window.addEventListener('OnRewards', (e: CustomEvent) => {
    // your code here
} as (e: Event) => void)

答案 3 :(得分:0)

我根据@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');
    }
  }
});