16

I think this has been addressed somewhere, at some point, just for the life of me I can't remember so here's my question:

I'm doing some javascript work that will be loaded into an existing application. This application has crap loads of functions available and hardly any of it is known to me except some that I want to actually use. So lets say that I know for a fact that window.srslyUsefulFunction will be available to me and I don't care much for porting this in to a typescript definition.

So the question is how do I use window.srslyUsefulFunction in my own typescript file without creating a definition for it?

Example:

class MyClass {
    public MyMethod (id : string) : void {
        // do something 
        var result = window.srslyUsefulFunction(id);
        // do something (with the result)
    }
}
Cerbrus
  • 70,800
  • 18
  • 132
  • 147
AlexR
  • 305
  • 1
  • 2
  • 10
  • `window` is a global object, your example should actually work, if the `srslyUsefulFunction` is declared in that scope. – Cerbrus Jan 02 '13 at 08:44
  • the problem isn't really the window object, but it's the srslyUsefulFunction that does not exist within my project but it will be available when this code is deployed. I'm pretty much adding some javascript as a "component" to an existing black-box system. I'm trying to use that black box methods in my generated js (ofcourse I won't be running this locally as that will most definitely fail) – AlexR Jan 02 '13 at 09:30

3 Answers3

18

You can add the function to the Window interface and then use it in your TypeScript program:

interface Window {
    srslyUsefulFunction(id: number): void;
}

class MyClass {
    doSomething() {
        window.srslyUsefulFunction(1);
    }
}
Fenton
  • 241,084
  • 71
  • 387
  • 401
  • This is good stuff and it seems a bit cleaner than the check-if-exists function, but there's honestly no way to use unchecked 'regular javascript' within a ts file? – AlexR Jan 02 '13 at 10:21
  • @AlexR: Unless I'm missing something that's typescript, this answer is simply overriding the function, opposed to what I'm doing. (which is actually how you polyfill a function in JavaScript) – Cerbrus Jan 02 '13 at 10:32
  • 4
    You can use regular JavaScript within a TypeScript file, but not if it extends something already defined in TypeScript, i.e. window is already declared as an implementation of the Window interface. If you were using the function withing `window.` - i.e. just pulling it from global scope, you could use `declare srslyUsefulFunction: (id: number): void;` or even the loose and easy `declare srslyUsefulFunction: any;` – Fenton Jan 02 '13 at 10:56
  • I'm picking this one as my answer as this is probably closest to what I actually ended up doing (prototyping boiling down the same thing) – AlexR Jan 02 '13 at 12:07
  • I found [link](http://stackoverflow.com/questions/12703266/how-to-handle-warnings-for-proprietary-custom-properties-of-built-in-objects-in/12703866#12703866) to be very useful – AlexR Jan 02 '13 at 13:05
  • 2
    This is VERY useful for a TS beginner. – Matthias Max Nov 24 '15 at 19:36
5

I have simple workaround.

In index.html

function playIntro() {
        intro = new lib.intro();
        onlinePlayer.contentContainer.addChild(intro);
        stage.update();
    }

in my Main.ts I call it like that:

private onClick(event): void {

        if (window.hasOwnProperty('playIntro')) {
            window['playIntro'].call();
        }
    }

So... if you want to call "blind" js function from global scope, just use window["foo"].call();

Kuba Bladek
  • 51
  • 1
  • 1
  • this is golden. it integrates pretty 'cleanly'. it's a downright dirty hack to begin with so why not add another hack to the hack! – JimB Feb 09 '18 at 19:37
  • I have an error with this: Do not access Object.prototype method 'hasOwnProperty' from target object no-prototype-builtins – user3713526 Oct 28 '21 at 17:44
  • if condition can be if ( Object.prototype.hasOwnProperty.call(window, 'playIntro') ) {; but i can't call the method without error: Element implicitly has an 'any' type because index expression is not of type 'number'; window['playIntro'].call(); – user3713526 Oct 28 '21 at 18:00
1

Check if the function exists. If it doesn't, declare it:

if(!window.hasOwnProperty('srslyUsefulFunction')
 || typeof window['srslyUsefulFunction'] !== "function"){
    window['srslyUsefulFunction'] = function(){
        console.log("You're only running a dummy implementation of srslyUsefulFunction here!");
    };
}
Cerbrus
  • 70,800
  • 18
  • 132
  • 147
  • This still wouldn't work in TypeScript because you would still get a warning about `window.srslyUsefulFunction` not being defined. You would have to extend the `Window` interface to clear this error. – Fenton Jan 02 '13 at 10:58
  • @SteveFenton, how about this way of checking if the function exists, then? (`typeof window.srslyUsefulFunction !== "function"` will only be checked if it exists) – Cerbrus Jan 02 '13 at 11:47
  • 1
    Your best bet is to try your code on the TypeScript Playground: http://www.typescriptlang.org/Playground/ – Fenton Jan 02 '13 at 11:54
  • @SteveFenton: It seems TypeScript doesn't know how to validate a case like that. Ugh, I guess it'll have to be array-like access then, even though it does exactly the same, it will validate. (*that* being: `window.hasOwnProperty('x') || typeof window.x !== "function"`) – Cerbrus Jan 02 '13 at 11:56
  • I was checking both solutions and fiddling a bit, the interface solution as Steve mentions isn't really as proper a solution as I thought, it still gives errors which isn't very elegant at all. Though it is doable for me since I'm dealing with a single js file with less than 200 loc. I'll use the code above, and I'll actually opt for something like: window.prototype.srslyUsefulFunction = new Object(); this in a seperate file outside of useful code. It's rather unfortunate that you can't insert unchecked lines – AlexR Jan 02 '13 at 12:04
  • @AlexR: glad I could've been of help! – Cerbrus Jan 02 '13 at 12:06