0
ユニオンタイプを使用して軽量イベントシステムを構築しようとしています。ユニオンタイプの1つのタイプのイベントをリスンすることができます。ここで私は(残念ながら、それは本当に種類を利用しない)、これまで持っているものです。ユニオンタイプの型保証イベントハンドラ
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);
なぜですか? 'インタフェースメッセージ{}'はそれを正確に行います。 –
申し訳ありませんが、あなたが正しいです。私は私のコメントを削除します。 –