Turns out that I needed an even smaller type of event: the signal. It is an event that has no data; it just fires. The Strongly Typed Events project started with the IEvent<TSender, TArgument> that was styled after the way .Net does event handling. Then the ISimpleEvent<TArgument> was added in 0.2.0, for scenarios when no sender is necessary. Now I’ve added the ISignal to version 0.3.0.

Why would we need another event type?

While programming a new TypeScript project, I got the need for a timer mechanism. I only need an event without data – much like a simple egg-timer. Implementing those events as an ISimpleEvent<void> looks ridiculous, that’s why I created the ISignal and its counterparts.

Traffic light example

Its usage is best illustrated with a piece of example code. Let’s create a somewhat static traffic light that will switch colors based on time. Remember: I’m Dutch, so the middle color will be orange!

class TrafficLight {

    private _signals = new SignalList();
    private _color = 'red';

    public constructor(
        public greenMs: number,
        public orangeMs: number,
        public redMs: number
    ) {
        this.onSwitchToGreen.subscribe(() => this._color = 'green');
        this.onSwitchToOrange.subscribe(() => this._color = 'orange');
        this.onSwitchToRed.subscribe(() => this._color = 'red');

        this.internalStart();
    }

    public get color(): string {
        return this._color;
    }

    public get onSwitchToGreen(): ISignal {
        return this._signals.get('green').asEvent();
    }

    public get onSwitchToRed(): ISignal {
        return this._signals.get('red').asEvent();
    }

    public get onSwitchToOrange(): ISignal {
        return this._signals.get('orange').asEvent();
    }

    private internalStart(): void {
        window.setTimeout(() => {
            this._signals.get('green').dispatch();
            window.setTimeout(() => {
                this._signals.get('orange').dispatch();
                window.setTimeout(() => {
                    this._signals.get('red').dispatch();
                    this.internalStart();
                }, this.orangeMs);
            }, this.greenMs)
        }, this.redMs)
    }
}

You can subscribe and unsubscribe from the signals in the usual way:

var light = new TrafficLight(5000, 1500, 10000);
light.onSwitchToGreen.subscribe(() => console.log('Light is green.'));
light.onSwitchToOrange.subscribe(() => console.log('Light is orange.'));
light.onSwitchToRed.subscribe(() => console.log('Light is red.'));

The usual suspects

All of the usual suspects are present:

  • ISignal – interface for signal event implementation and exposure.
  • SignalDispatcher – implementation of a signal with a dispatch method.
  • SignalList – implements named storage of auto created signals. Useful you need to implement a lot of them.
  • SignalHandlingBase – to give your class named signal capabilities.

Other changes

I’ve removed the version numbers from the file names which makes updating easier. The tests are now wrapped in modules and have a string comment attached to them.

Check Strongly Typed Events for TypeScript on GitHub.