0
我試圖建立工會使用的類型,在那裏我可以監聽來自於工會一類的事件一個輕量級的事件系統。這裏是我到目前爲止(不幸的是,它並沒有真正利用類型):類型安全事件處理聯合類型
class EventSystem {
events: { [key: string]: { (event: EventType) }[] };
constructor() {
this.events = {};
}
emit(key: string, event: EventType): void {
var arr = this.events[key];
for (let i = 0; i < arr.length; ++i) {
arr[i](event);
}
}
on(key: string, callback: (event: EventType) => void) {
if (key in this.events) {
this.events[key].push(callback);
} else {
this.events[key] = [callback];
}
}
}
interface EventA {
foo: Number
}
interface EventB {
bar: Number
baz: string
}
type EventType = EventA | EventB
const EventNames = {
EventA: 'EventA',
EventB: 'EventB'
}
let x = {foo: 2} as EventA;
let y = {
bar: 4,
baz: "test"
} as EventB;
let es = new EventSystem();
es.on(EventNames.EventA, function (a: EventA) {
console.log(a);
});
//Triggers the on above
es.emit(EventNames.EventA, x);
//Unfortunately, this also triggers the on above
es.emit(EventNames.EventA, y);
我真正想要的是這樣的:
let es = new EventSystem<EventType>();
es.on<EventA>(function (a) {
//a is inferred to be EventA
console.log(a);
});
//Triggers the on above
es.emit(x);
//Will not trigger the on, since the type does not match
es.emit(y);
//Type error, since number is not in EventType
es.emit(4);
是這樣的可能的打字稿?如果沒有,有沒有比我在做什麼更類型安全的方法嗎?或者更好的方式來獲得這種類型的行爲?
編輯:
現在,我做以下。它增加了很多的樣板到的EventSystem類(我有數百個消息類型),也使得API在我看來有點醜陋,但至少我得到的類型安全。重複的代碼量讓我覺得必須有一個更好的辦法。
class EventSystem {
events: {[P in EventNames]: { (event: EventType) }[]} = {
'EventA': [],
'EventB': []
};
emitEventA(event: EventA): void {
this.events['EventA'].forEach((eventFunc) => eventFunc(event));
}
emitEventB(event: EventB): void {
this.events['EventB'].forEach((eventFunc) => eventFunc(event));
}
onEventA(callback: (event: EventA) => void) {
this.events['EventA'].push(callback);
}
onEventB(callback: (event: EventB) => void) {
this.events['EventB'].push(callback);
}
}
interface EventA {
foo: Number
}
interface EventB {
bar: Number
baz: string
}
type EventType = EventA | EventB
type EventNames = 'EventA' | 'EventB'
let x = { foo: 2 } as EventA;
let y = {
bar: 4,
baz: "test"
} as EventB;
let es = new EventSystem();
es.onEventA(function (a) {
console.log(a);
});
//Triggers the on above
es.emitEventA(x);
//Correctly caught now
es.emitEventA(y);
爲什麼? '接口消息{}'正是這樣做的。 –
對不起,你說得對。我會刪除我的評論。 –