请编写一个类型安全的基于ts的eventbus
时间: 2023-06-07 07:10:50 浏览: 106
好的,我会为您编写一个基于 TypeScript 的类型安全的 EventBus。
首先,我们需要定义一个监听器的类型,每个监听器都需要知道事件的名称和处理事件时接收的参数类型:
```typescript
interface Listener<E extends keyof Events> {
event: E;
handler: (args: Events[E]) => void;
}
```
这里的 `Events` 是我们定义的事件类型。
接下来,我们需要定义一个 `EventBus` 类,这个类将负责监听事件、触发事件以及添加和删除监听器:
```typescript
class EventBus<Events extends Record<string, any>> {
private listeners: Record<string, Array<Listener<keyof Events>>> = {};
public on<E extends keyof Events>(event: E, handler: Listener<E>['handler']) {
if (!this.listeners[event]) {
this.listeners[event] = [];
}
this.listeners[event].push({ event, handler } as Listener<any>);
}
public off<E extends keyof Events>(event: E, handler: Listener<E>['handler']) {
const listeners = this.listeners[event];
if (listeners) {
this.listeners[event] = listeners.filter(l => l.handler !== handler);
}
}
public emit<E extends keyof Events>(event: E, args: Events[E]) {
const listeners = this.listeners[event];
if (listeners) {
listeners.forEach(l => l.handler(args));
}
}
}
```
这个 `EventBus` 类的泛型参数 `Events` 表示所有可能触发的事件,其实就是一个对象类型的集合。在 `on` 方法中,我们创建了一个新的监听器并将其添加到对应事件的监听器列表中,如果该事件的监听器列表尚不存在,则会将该列表初始化为空数组;在 `off` 方法中,我们删除一个具体事件的监听器;在 `emit` 方法中,我们触发一个具体事件,并将参数传递给所有监听器。
现在,假设我们有一个 `User` 类和一个 `update` 事件,我们可以这样使用 EventBus:
```typescript
interface Events {
update: { id: number; name: string };
}
class User {
public name: string;
public eventbus = new EventBus<Events>();
constructor(name: string) {
this.name = name;
}
public updateName(newName: string) {
this.name = newName;
const id = Math.floor(Math.random() * 100);
this.eventbus.emit('update', { id, name: this.name });
}
}
const user = new User('Alice');
user.eventbus.on('update', ({ id, name }) => {
console.log(`User ${id} has been updated to "${name}"`);
});
user.updateName('Bob');
```
在这个例子中,我们定义了一个 `User` 类,其具有一个 `updateName` 方法,用于更新用户名,并在修改完成后触发 `update` 事件。我们在 `User` 类中创建了一个 `eventbus` 属性,它是 `EventBus` 的实例,并将 `Events` 对象作为泛型参数传递给它。我们使用 `on` 方法来监听 `update` 事件,使用 `emit` 方法在更新完成后触发该事件。
在 `on` 方法中,我们传递一个函数参数,它接收一个 `update` 事件的参数。因为我们已经使用泛型约束了 `EventBus` 类的类型,所以事件的名称和参数类型都是类型安全的。
希望这个示例对你有所帮助,如果你有问题,请随时向我提问。
阅读全文