繁体   English   中英

“(e:CustomEvent)=> void”类型的参数不可分配给“EventListenerOrEventListenerObject”类型的参数

[英]Argument of type '(e: CustomEvent) => void' is not assignable to parameter of type 'EventListenerOrEventListenerObject'

我有这个自定义事件设置,它适用于 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)=> void”中缺少属性“handleEvent”。

我不确定要在这里做什么来解决这个问题。

这是由于 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"不是已知的事件类型......除非您使用声明合并使其为人所知:

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

或者,如果您在一个模块内(其中有任何export ),请使用全局扩充

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

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

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

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

jcalz 的优秀答案的基础上,您还可以使用类型断言来更简洁:

window.addEventListener('OnRewards', (e: Event) => {
    const detail = (<CustomEvent>e).detail;
    ...
});

你也有这个选项:

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

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

正如 Yukulélé 对 jcalz 的回答所评论的那样,您还可以检查CustomEvent是否是Event的实例。

像下面这个例子:

window.dispatchEvent(
  new CustomEvent('customEventName', {
    detail: { something: true },
  })
);

window.addEventListener('customEventName', (e: Event) => {
  if (e instanceof CustomEvent) {
    if (e?.detail?.something) {
      // do something
    }
  }
});

是的,另一种满足编译器的方法是转换事件对象,例如yourFuctionName(e: Event){ const event = e as CustomEvent <SegmentChangeEventDetail>; console.log(event.detail)} yourFuctionName(e: Event){ const event = e as CustomEvent <SegmentChangeEventDetail>; console.log(event.detail)}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM