A¬†while ago I started a GitHub project for Strongly Typed Events¬†in TypeScript. I’ve uploaded the second version (0.2) with support for Simeple Events (ISimpleEvent<TArgs>) and I changed the way you can expose the dispatcher as an event. The code is 100% backwards compatible with version 0.1 – you might need to update some references.

Introducing ISimpleEvent<TArgs>

The IEvent<TSender, TArgs> is modeled after .Net’s implementation of the EventHandler. Some projects might not feel comfortable with the sender argument or may prefer to add the sender to the TArgs¬†object or disregard it entirely. That’s why I’ve added the ISimpleEvent<TArgs> to the project. It makes life a little bit easier. Consider the following code:

class ImageDownloader {

    private _ondownload: SimpleEventDispatcher<ImageDownloadArg> 
                                    = new SimpleEventDispatcher();

    public get ondownload(): ISimpleEvent<ImageDownloadArg> {
        return this._ondownload.asEvent();
    }

    public download(url: string, callback?: ISimpleEventHandler<ImageDownloadArg>) {

        let img = new Image();

        img.onload = () => {

            let result = new ImageDownloadArg(url, img.height, img.width);

            if (callback) {
                callback(result);
            }

            this._ondownload.dispatch(result);
        };

        img.src = url;
    }
}

class ImageDownloadArg {

    private _url: string;
    private _height: number;
    private _width: number;

    constructor(url: string, height: number, width: number) {
        this._url = url;
        this._height = height;
        this._width = width;
    }

    public get url(): string {
        return this._url;
    }

    public get height(): number {
        return this._height;
    }

    public get width(): number {
        return this._width;
    }
}

The code uses the same concepts as a IEvent<TSender, TArgs>: a dispatcher and an interface.

Minimizing dispatcher exposure

Another major new feature is a new way to minimize exposure of the dispatcher object. The dispatcher is an easy way to add a single event to a class. In version 0.1 an event could be implemented using the following code:

interface MyEventArgument { }

class MyClass {

    private _myEvent: EventDispatcher<MyClass, MyEventArgument>
                        = new EventDispatcher<MyClass, MyEventArgument>();

    get myEvent(): IEvent<MyClass, MyEventArgument> {
        return this._myEvent;
    }
}

In the TypeScript world, everything is well, but in the JavaScript world we are now exposing our dispatcher. Some JS might¬†now call the dispatch method, which might be very undesirable. That’s why the dispatcher now has an asEvent method that will return a wrapped dispatcher that implements the¬†subscribe and¬†unsubscribe methods. In version 0.2 events¬†can be exposed like:

    get myEvent(): IEvent<MyClass, MyEventArgument> {
        return this._myEvent.asEvent();
    }

Asynchronous event execution

Some events might take a while to execute, that’s why I added an option to do asynchronous event execution. The code looks like this:

/**
* Dispatches the events thread.
* @param sender The sender.
* @param args The arguments object.
*/
dispatchAsync(sender: TSender, args: TArgs): void {
    for (let handler of this._subscriptions) {
        this.excuteAsync(sender, args, handler);
    }
}

private excuteAsync(sender: TSender, args: TArgs, handler: IEventHandler<TSender, TArgs>): void {
    window.setTimeout(() => handler(sender, args), 0);
}

Using an asynchronous approach is as easy as replacing the calls to dispatch with dispatchAsync.

Documentation

I also improved documentation, both in the TS files (JavaDoc) and in .md form as some “How To’s”: