Wednesday, 10 October 2012

Creating TypeScript type declaration file for an existing jQuery plugin

Microsoft recently announced a scripting language that compiles into JavaScript. It is known as TypeScript.
TypeScript is super set of JavaScript. Using TypeScript, one can write type safe client side script. If you are not familiar with TypeScript yet, you may checkout the following resources:


Any existing JavaScript library can be used with TypeScript if a type declaration file is created for the library. A type declaration file provides a TypeScript interface to interact with the library. TypeScript team has created the declaration files for jQuery and Node.js libraries.

In this post, we will create a TypeScript declaration file for jQuery-idle Timeout plugin. It is a small plugin which signs off the user if the user didn’t interact with the page for some time. Using this plugin is very easy. Following is an example of the usage:
$(document).idleTimeout({
    inactivity: 5000,
    noconfirm: 1000,
    sessionAlive: 1000,
    redirect_url: 'TimedOut.html',
    click_reset: true,
    alive_url: 'default.htm',
    showDialog: false
});

The above script sets redirects user to the page TimedOut.html if the user didn’t interact with the page for 5 seconds or more.
From the usage of the plugin, it is clearly visible that,

  • The function idleTimeout is invoked using jQuery object
  • The function idleTimeout accepts a set of options
In the source of jQuery-idleTimeout plugin, we see the following assignment statement in the beginning:
var defaults = {
            inactivity: 1200000, //20 Minutes
            noconfirm: 10000, //10 Seconds
            sessionAlive: 30000, //10 Minutes
            redirect_url: '/js_sandbox/',
            click_reset: true,
            alive_url: '/js_sandbox/',
            logout_url: '/js_sandbox/',
            showDialog: true
        }

From here, we get to know the list of configurable options. As TypeScript is strongly typed, we need to define an interface to hold the above properties. One important thing to remember here is that, the fields should be made nullable in the interface.  

The interface can be as follows:
interface JQIdleTimeoutSettings {
    inactivity?: number;
    noconfirm?: number;
    sessionAlive?: number;
    redirect_url?: string;
    click_reset?: bool;
    alive_url?: string;
    logout_url?: string;
    showDialog?: bool;
    }


The function idleTimeout is invoked using a jQuery object. In the declaration file of jQuery, an interface is defined to hold all functions which have to be invoked using jQuery objects. Name of the interface is JQuery.

We shouldn’t modify the source of jQuery’s declaration file to add the idleTimeout function. Instead, we have to define an interface extending JQuery as follows:
interface JQueryTimeout extends JQuery {
    idleTimeout(settings: JQIdleTimeoutSettings): JQueryTimeout;
}

I made the declaration file open on GitHub. You can find it here.

Using the declaration file:
To use the declaration file in a TypeScript file, a reference of the declaration file should be added. Calling the idleTimeout function in TypeScript is quite similar to that of in JavaScript code. Only difference being, we need to type cast the jQuery object to type of JQueryTimeout.
/// <reference path="jQueryIdleTimeout.d.ts" />

(<JQueryTimeout>$(document)).idleTimeout({
                inactivity: 5000,
                noconfirm: 1000,
                sessionAlive: 1000,
                redirect_url: 'TimedOut.html',
                click_reset: true,
                alive_url: 'default.htm',
                showDialog: false
});
This is because, in TypeScript, $(document) returns an object of type JQuery. The function idleTimeout is declared in the interface JQueryTimeout, which is extended from the interface JQuery.

Happy coding!

8 comments:

  1. Ravi, Great post! I tried this and wrote a declaration file for some library. I believe it is fine now but I think when it gets larger it will be prune to mistakes. How can I check the syntax of the mydeclarations.d.ts file?

    In the command line I did:

    $ tsc mydeclarations.d.ts

    and got:

    SyntaxError: interface is a reserved identifier

    :(

    ReplyDelete
  2. Ignacio,
    Glad that you found it useful.
    You might be using the word interface to name a variable or function. Interface is a keyword in TypeScript.
    If you are using VS, I recommend you to install Web Essentials. It makes writing TypeScript very easy on VS.

    ReplyDelete
  3. Ah! got it!. Thank you very much.
    Unfortunately I am in the Mac so i am struggling a bit with Sublime Text for now.

    ReplyDelete
  4. Concise and practical post

    ReplyDelete
  5. Thank you for this article. Could you please tell me where to add this into Angular CLI?

    Thank you very much!

    ReplyDelete
  6. Hello,

    OK, I found out, that I can use the typings.d.ts to do that.

    Sadly, after including your (modified) interfaces (I want to include jQuery.ScannerDetection - http://a.kabachnik.info/jquery-scannerdetection-tutorial.html) and add the script reference into the 'scripts' array in .angular-cli.json I still get the error 'TypeError: $(...).scannerDetection is not a function.'

    Do you have any idea what I could have missed?
    Thanks and regards.

    ReplyDelete

Note: only a member of this blog may post a comment.