我正在尝试创建一个类型EventEmitter,但是我不能强制要求传递给泛型的接口是EventMap类型的,而没有TypeScript的抱怨。
type EventHandler = () => void
type EventMap = Record<string, EventHandler>
interface EventListener {
handler: EventHandler
once: boolean
}
export class Emitter<Events extends EventMap> {
private listeners = new Map<keyof Events, EventListener[]>()
private addListener<E extends keyof EventMap>(type: E, listener: EventListener) {
const listeners = this.listeners.get(type) || []
this.listeners.set(type, [...listeners, listener])
}
@bind
public on<E extends keyof EventMap>(type: E, handler: Events[E]) {
this.addListener(type, { handler, once: false })
}
}
interface TestEvents {
test: (a: number) => void,
}
class Test extends Emitter<TestEvents> {}给我
Type 'TestEvents' does not satisfy the constraint 'Record<string, EventHandler>'.
Index signature is missing in type 'TestEvents'.发布于 2018-11-26 14:29:49
您需要对其进行稍微不同的约束,您希望Events的所有键都是EventHandlers,而Events不一定要有索引签名。您可以使用以下内容:
type EventHandler = (...a: any[]) => void
interface EventListener {
handler: EventHandler
once: boolean
}
export class Emitter<Events extends Record<keyof Events, EventHandler>> {
private listeners = new Map<keyof Events, EventListener[]>()
private addListener<E extends keyof Events>(type: E, listener: EventListener) {
const listeners = this.listeners.get(type) || []
this.listeners.set(type, [...listeners, listener])
}
public on<E extends keyof Events>(type: E, handler: Events[E]) {
this.addListener(type, { handler, once: false })
}
}
interface TestEvents {
test: (a: number) => void,
}
class Test extends Emitter<TestEvents> { }
new Test().on("test", a => a.toExponential) // a is number.但是,这种方法存在一个问题,如果地图中有多个事件(可能会有),类型记录将无法推断参数类型。
interface TestEvents {
test: (a: number) => void,
test2: (a: number) => void,
}
class Test extends Emitter<TestEvents> { }
new Test().on("test", a => a.toExponential) // a is any这是可以修复的,但是类型变得更加复杂,请参阅here获得一个非常类似的想法。
发布于 2018-11-26 14:07:15
因为Record是:
type Record<K extends string, T> = {
[P in K]: T;
}您缺少定义的索引:
interface TestEvents {
test: () => void;
[index: string] : EventHandler;
}而且,您的测试方法是无效的,因为它不符合EventHandler的要求,不强制该方法上的任何参数。
这个怎么样:
export interface EventMap extends Record<string, EventHandler>{
[index: string]: EventHandler;
event1: () => void;
event2: () => void;
}现在存在所需的索引器,但您强制类拥有event1和event2。
https://stackoverflow.com/questions/53482637
复制相似问题