我有一个简单的事件分派器类,该类使用类似于DOM类型定义上的addEventListener
的方法以及将事件名称映射到事件类的事件映射。
interface EventMap {
[type: string]: any // tslint:disable-line no-any
}
type Listener<T, K extends keyof T> = (event: T[K]) => void
export class Dispatcher<T extends EventMap, K extends keyof T = keyof T> {
/**
* The current list of listeners.
*/
private listeners: { [key: string]: Listener<T, K>[] } = {}
/**
* Add a new event listener.
*
* @param type The type of event to list to.
* @param listener The function that should be called when the event is dispatched.
*/
addEventListener<EventType extends K> (type: EventType, listener: Listener<T, EventType>): void {
// Workaround: Type 'EventType' cannot be used to index type '{ [key: string]: Listener<T, K>[]; }'
const key: string = type as string
if (! (key in this.listeners)) {
this.listeners[key] = []
}
this.listeners[key].push(listener)
}
/**
* Remove an event listener.
*
* @param type The type of event to remove a listener for. If no listener is
* given, all event listeners for this type will be removed.
* @param listener The listener to remove.
*/
removeEventListener<EventType extends K> (type: EventType, listener?: Listener<T, EventType>): void {
const key: string = type as string
if (! (key in this.listeners)) {
return
}
if (listener) {
const index = this.listeners[key].indexOf(listener)
if (index === -1) {
return
}
this.listeners[key].splice(index, 1)
} else {
delete this.listeners[key]
}
}
/**
* Dispatch an event.
*
* @param type The type of event to dispatch.
* @param event The event payload.
*/
dispatch<EventType extends K> (type: EventType, event: T[EventType]): void {
const key: string = type as string
if (! (key in this.listeners)) {
return
}
this.listeners[key].forEach(listener => listener(event))
}
}
将使用类似这样的内容:
class ChangeEvent {
constructor (public readonly value: string) {
}
}
interface EventMap {
'change': ChangeEvent
}
const dispatcher = new Dispatcher<EventMap>()
这很好,但是自从Typescript 3.4(从3.3版)更新以来,我在添加和查找侦听器数组,push
和indexOf
调用的事件侦听器的行上遇到类型错误
Argument of type 'Listener<T, EventType>' is not assignable to parameter of type 'Listener<T, K>'.
Type 'K' is not assignable to type 'EventType'.
Type 'keyof T' is not assignable to type 'EventType'.
Type 'string | number | symbol' is not assignable to type 'EventType'.
Type 'string' is not assignable to type 'EventType'.
我可能做错了什么,但看不到。 EventType
扩展了K
,为什么这不起作用?对于我来说,“类型'string'不能分配给类型'EventType'”尤其没有意义,因为keyof T
肯定会包含string
。