javascriptjquerytypescript1.4

Typescript + jQuery: correct way to use event state?


I have some simple popstate code for an SPA as follows:

module myModule {
    $(function () {
        $(window).on("popstate", function(e) {
            if (e.originalEvent.state !== null) {
                // code removed
            }
        });
    });
}

(The use of originalEvent is due to answers like this: popstate returns event.state is undefined)

This gives a compile error:

Property 'state' does not exist on type 'Event'.

e is a JQueryEventObject type and originalEvent is an Event type.

Now I've managed to work around the problem by defining this interface:

interface EventWithState extends Event {
    state: any;
}

(*I doubt "any" is really my best option here - if anyone knows what type state should be let me know, and more importantly how do I find that out for myself in such cases)

And I changed my above code like so:

module myModule {
    $(function () {
        $(window).on("popstate", function(e) {
            if ((<EventWithState>e.originalEvent).state !== null) {
                // code removed
            }
        });
    });
}

OK that works fine now and compiles to the original code I wanted. But it seems like an awkward workaround.

Is this the acceptable method to do this? Is something missing from typescript definitions? Or is there something I am missing.

Furthermore using e.state also doesn't work, however editing jquery.d.ts (from DefinitelyTyped) and adding state: any; to BaseJQueryEventObject fixes it in a similar way to my workaround. This is what makes me think something is missing from definitions for typescript regarding the Event state.


Solution

  • Thanks to Pilot for sharing the answer to another question, though it seemed unrelated at first, it did hold the clues and links for me to work out that I could cast to PopStateEvent rather than my own EventWithState.

    module myModule {
        $(function () {
            $(window).on("popstate", function(e) {
                if ((<PopStateEvent>e.originalEvent).state !== null) {
                    // code removed
                }
            });
        });
    }
    

    https://developer.mozilla.org/en-US/docs/Web/API/Event

    https://developer.mozilla.org/en-US/docs/Web/API/PopStateEvent

    And for the record, lib.d.ts does use "any" as the type for state:

    interface PopStateEvent extends Event {
        state: any;
        initPopStateEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, stateArg: any): void;
    }
    

    https://typescript.codeplex.com/SourceControl/latest#bin/lib.d.ts