# Adding named events to your TypeScript classes (Part 4)

**Date:** 2016-03-27  
**Author:** Kees C. Bakker  
**Categories:** Strongly Typed Events, TypeScript  
**Original:** https://keestalkstech.com/adding-named-events-to-your-class-part-4/

![Adding named events to your TypeScript classes (Part 4)](https://keestalkstech.com/wp-content/uploads/2016/03/lightning-bolt-1203953_1280.png)

---

In a [previous tutorial I explained how events can be implemented](https://keestalkstech.com/2016/03/strongly-typed-event-handlers-in-typescript-part-1/) as properties on a class using [Strongly Typed Events for TypeScript](https://github.com/KeesCBakker/Strongly-Typed-Events-for-TypeScript). In this tutorial I explore how you can give your classes named events using an `IEventHandling` interface or `EventHandlingBase` class.

## Create an IEventHandling<TSender, TArgs>

First, let's inspect the interface.

```ts
/** Indicates the object is capable of handling named events. */
interface IEventHandling<TSender, TArgs> {

    subscribe(name: string, fn: (sender: TSender, args: TArgs) => void): void;

    unsubscribe(name: string, fn: (sender: TSender, args: TArgs) => void): void;
}
```

It looks like the `IEvent` interface, but it adds a name to the subscriptions.

## Implement IntervalEventTester

I don't have a real life example for this feature. For now let's build an event generator that generates an event every x milliseconds.

```ts
class IntervalEventTester implements IEventHandling<IntervalEventTester, number>
{
    private _nr: number = 0;
    private _events: EventList<IntervalEventTester, number> = new EventList<IntervalEventTester, number>();

    constructor(interval: number) {
        setInterval(() => {
            let nr = this._nr += 1;
            this._events.get('ev-' + nr).dispatch(this, nr);
            this._events.remove('ev-' + nr);
        }, interval);
    }

    subscribe(name: string, fn: (sender: IntervalEventTester, args: number) => void): void {
        this._events.get(name).subscribe(fn);
    }

    unsubscribe(name: string, fn: (sender: IntervalEventTester, args: number) => void): void {
        this._events.get(name).unsubscribe(fn);
    }
}
```

I used an [`EventList`](https://keestalkstech.com/2016/03/strongly-typed-events-in-typescript-using-an-event-list-part-3/) to implement the `IEventHandling` interface as it stores events by name. We're basically exposing its features to the outside.

Using the events is pretty simple:

```ts
let x = new IntervalEventTester(100);

x.subscribe('ev-10', () => alert('EV-10 fired!'));
x.subscribe('ev-24', () => alert('EV-24 fired!'));
```

A disadvantage is this method is *discoverability.* The user can't look to the class signature to discover possible events.

## Extending from EventHandlingBase<TSender, TArgs>

For convenience there is a base class that can be extended to do the same. It implements the ceremony and provides access to the events through a protected property.

```ts
/** Extends objects with event handling capabilities. */
abstract class EventHandlingBase<TSender, TArgs> implements IEventHandling<TSender, TArgs> {

    private _events: EventList<TSender, TArgs> = new EventList<TSender, TArgs>();

    protected get events(): EventList<TSender, TArgs> {
        return this._events;
    }

    subscribe(name: string, fn: (sender: TSender, args: TArgs) => void): void {
        this._events.get(name).subscribe(fn);
    }

    unsubscribe(name: string, fn: (sender: TSender, args: TArgs) => void): void {
        this._events.get(name).unsubscribe(fn);
    }
}
```

Note: this scenario is not applicable to all classes as *polymorphy* (multiple base classes) is not supported by TypeScript. This would be a great case for [extension methods in TypeScript](https://github.com/Microsoft/TypeScript/issues/9).

Our implementation with the base class makes things cleaner:

```ts
class IntervalEventTester2 extends EventHandlingBase<IntervalEventTester2, number>
{
    private _nr: number = 0;

    constructor(interval: number) {

        super();

        setInterval(() => {
            let nr = this._nr += 1;
            this.events.get('ev-' + nr).dispatch(this, nr);
            this.events.remove('ev-' + nr);
        }, interval);
    }
}
```

## More

Check out the following:
