Strongly typed event handlers in TypeScript (Part 1)

As a C# programming I have a lot of interest in the TypeScript project. Lately I've been playing around with it to look what it can do. I found myself in need of some event handling, so I decided to build something that looks like the event handling .Net gives you. It grew into Strongly Typed Events for TypeScript. This tutorial is part of a series.
2018-02: we've updated to a new version of the project. The article matches the latest version. Get the latest version by running: npm install strongly-typed-events --save
The IEvent<TSender, TArgs>
An event is defined as a pair of sender and event arguments. It's leveraging generics to make them strongly typed. Note: the actual interface in the project is a little bit more complex.
/** Models an event with a generic sender and generic arguments */
interface IEvent<TSender, TArgs> {
subscribe(fn: (sender: TSender, args: TArgs) => void): void;
unsubscribe(fn: (sender: TSender, args: TArgs) => void): void;
}
Example implementation: a pulse generator
Let's create a pulse generator that will trigger an event based on the given the frequency in Hertz. I'm using the EventDispatcher from the package:
class PulseGenerator {
//create private event dispatcher
private _onPulsate = new EventDispatcher();
frequencyInHz: number;
//expose the event dispatcher through the IEvent interface
//this will hide the dispatch method outside the class
get onPulsate(): IEvent {
return this._onPulsate.asEvent();
}
constructor(frequencyInHz: number) {
this.frequencyInHz = frequencyInHz;
this.start();
}
private start() {
window.setTimeout(() => {
this.start();
//dispatch event by calling the dispatcher
this._onPulsate.dispatch(this, this.frequencyInHz);
}, 1000 / this.frequencyInHz);
}
}
Now let's subscribe to the event and beep each time we receive a pulse.
var generator = new PulseGenerator(1);
//subscribe on the onPulse event
generator.onPulsate.subscribe((p, hz) => {
//play beep:
var snd = new Audio("data:audio/wav;base64,UklGRkYDAABXQVZFZm10IBAAAAABAAEAQB8AAIA+AAACABAAZGF0YSIDAAAAADM1FVYVVjM1AADNyuup66nNygAAMzUVVhVWMzUAAM3K66nrqc3KAAAzNRVWFVYzNQAAzcrrqeupzcoAADM1FVYVVjM1AADNyuup66nNygAAMzUVVhVWMzUAAM3K66nrqc3KAAAzNRVWFVYzNQAAzcrrqeupzcoAADM1FVYVVjM1AADNyuup66nNygAAMzUVVhVWMzUAAM3K66nrqc3KAAAzNRVWFVYzNQAAzcrrqeupzcoAADM1FVYVVjM1AADNyuup66nNygAAMzUVVhVWMzUAAM3K66nrqc3KAAAzNRVWFVYzNQAAzcrrqeupzcoAADM1FVYVVjM1AADNyuup66nNygAAMzUVVhVWMzUAAM3K66nrqc3KAAAzNRVWFVYzNQAAzcrrqeupzcoAADM1FVYVVjM1AADNyuup66nNygAAMzUVVhVWMzUAAM3K66nrqc3KAAAzNRVWFVYzNQAAzcrrqeupzcoAADM1FVYVVjM1AADNyuup66nNygAAMzUVVhVWMzUAAM3K66nrqc3KAAAzNRVWFVYzNQAAzcrrqeupzcoAADM1FVYVVjM1AADNyuup66nNygAAMzUVVhVWMzUAAM3K66nrqc3KAAAzNRVWFVYzNQAAzcrrqeupzcoAADM1FVYVVjM1AADNyuup66nNygAAMzUVVhVWMzUAAM3K66nrqc3KAAAzNRVWFVYzNQAAzcrrqeupzcoAADM1FVYVVjM1AADNyuup66nNygAAMzUVVhVWMzUAAM3K66nrqc3KAAAzNRVWFVYzNQAAzcrrqeupzcoAADM1FVYVVjM1AADNyuup66nNygAAMzUVVhVWMzUAAM3K66nrqc3KAACJNO5T2lKKMgAAys50sYeyydAAAOMtK0kYSOQrAABx1Ta8Sr1v1wAAPCdoPlU9PiUAABfc+cYMyBbeAACWIKYzkjKXHgAAveK70c/SvOQAAO8Z4yjQJ/EXAABk6X7ckd1j6wAASRMhHg0dShEAAArwQedU6AnyAACjDF4TSxKkCgAAsfYD8hfzr/gAAPwFnAiIB/0DAABX/cb82f1W/wAA");
snd.play();
});
//change frequency
setTimeout(function () {
generator.frequencyInHz = 2;
}, 3000);
More
Check out the following:
- Strongly typed event handlers in TypeScript (Part 1)
- Using strongly typed events in TypeScript with interfaces (Part 2)
- Strongly Typed Events in TypeScript using an event list (Part 3)
- Adding named events to your classes (Part 4)
- GitHub: https://github.com/KeesCBakker/Strongly-Typed-Events-for-TypeScript