is it possible to override a window function?

Topics: General
Oct 11, 2012 at 5:31 PM
Edited Oct 11, 2012 at 5:32 PM

When I try this:

 

            if (!window.requestAnimationFrame) {
                window.requestAnimationFrame = this.addSetTime;
            }

 

I get an error complaining that the signature for addSetTime doesn't match requestAnimationFrame. This isn't a valid error however because I'm only re-assigning it when window.requestAnimationFrame doesn't exist.

Is there a way to force the compiler to accept this new function?

Oct 11, 2012 at 5:54 PM

It's a valid error because any time you refer to requestAnimationFrame subsequently the compiler will be using the type that's defined on the window for that method.

If your method is actually compatible (that is, it can be called using the existing signature for requestAnimationFrame even though the types are different), you can cast your method to the type that the compiler is expecting. (Use an intermediate cast to <any> if necessary).

If your method is not compatible, you could change your definition of addSetTime so that it matches the expected signature and semantics.

Alternatively, you can change the definition of window.requestAnimationFrame, but you shouldn't do that unless you really think the existing definition is incorrect.

In typescript, casts are type annotations that appear in angle brackets in front of the expression being cast.

Oct 11, 2012 at 6:05 PM

I understand why the compiler does it, but it makes adding shims extremely difficult (if not impossible).

Oct 11, 2012 at 6:19 PM

Not difficult or impossible. I outlined 3 ways:

1. Cast

2. Adjust your method definition so that it actually matches

3. Redefine window.requestAnimationFrame

I should have added a 4th:

4. Use a lambda to convert from the types expected by window.requestAnimationFrame to the types used by your function

All of these are easy to do. Do you need to see the code for these? 

Oct 11, 2012 at 6:34 PM
Edited Oct 11, 2012 at 8:50 PM

You can cast like this:

if (!window.requestAnimationFrame) {

    window.requestAnimationFrame = <(callback:FrameRequestCallback) => number><any>this.addSetTime;

}

or simply like this:

if (!window.requestAnimationFrame) {

    window.requestAnimationFrame = <any>this.addSetTime;

}

Or you can adapt like this:

if (!window.requestAnimationFrame) {

    window.requestAnimationFrame = (callback) => {

            this.addSetTime(); return 0;

    };

}

Let me know if you need more info.

Oct 11, 2012 at 6:36 PM
Edited Oct 11, 2012 at 6:37 PM

Edit as I review your post (which was made as I typed my reply)

Oct 12, 2012 at 11:14 AM

Thank you for posting the examples, but they all suffer from the same problem - if window.x doesn't exist the compiler won't let it through. Here's a better example to demonstrate what I mean:

Microsoft use URL.createObjectURL and URL.revokeObjectURL which I use when handling the data from xhr requests. However most vendors use window.URL or even window.webkit.URL.

You cannot do:

if (!window.URL) { blah blah }

because Visual Studio will error-mark the URL part claiming "The property URL does not exist on the object window". It only doesn't exist because TypeScript is using Microsoft's supplied definition file. Now I really don't want to edit this file, but unless you can think of a way to allow the above through the compiler I'm a bit stuck.

Oct 12, 2012 at 1:30 PM
Edited Oct 12, 2012 at 1:31 PM

Have you tried:

 

interface Window { URL: string; }

if (!window.URL) { blah blah }

Hope this helps

Jay

Oct 12, 2012 at 1:53 PM

Nice, trying that now. Also trying:

window['URL']
One of them must surely work!