0

I am trying to log when a method is called automatically. (I got coding from https://stackoverflow.com/a/5034657/11188822)

augment(withFn) {
        let name, fn;
        for (name in window) {
            fn = window[name];
            if (typeof fn === 'function') {               
                window[name] = (function(n, f) {   // I get an error here.
                    const args = arguments;
                    return function() {
                        withFn.apply(this, args);
                        return fn.apply(this, arguments);
                    };
                })(name, fn);
            }
        }
    }

and call this.

this.augment(function(name, fn) {
        console.log('calling ' + name);
    });

I get an error

ERROR in src/app/app.component.ts(81,17): error TS2740: Type '() => any' is missing the following properties from type 'Window': Blob, TextDecoder, TextEncoder, URL, and 232 more.

How can I override window function ?

Aleksey L.
  • 35,047
  • 10
  • 74
  • 84
sally
  • 379
  • 2
  • 8
  • 17

1 Answers1

1

TypeScript treats your window[name] property as a Window interface that should contain Blob, TextDecoder, TextEncoder etc.

The reason for this is that Window interface includes definition for dynamic property:

interface Window extends EventTarget, WindowTimers, ... {
  ...
  [index: number]: Window;
}

which represents a reference to the window object in the frames(window[0], window[1], etc.)

You can extend the existing Window interface to tell it about your case:

declare global {
  interface Window {
    [index: string]: () => any; // or just any
  }
}

also you must explicitly say that the variable let name is type of string:

let name: string

Here's the full code:

app.component.ts

export class AppComponent {
  ...

  ngOnInit() {
    this.augment(function(name, fn) {
        console.log('calling ' + name);
    });
  }

  augment(withFn) {
    let name: string, fn;
    for (name in window) {
      fn = window[name];
      if (typeof fn === 'function') {
        window[name] = (function (n, f) {
          const args = arguments;
          return function () {
            withFn.apply(this, args);
            return fn.apply(this, arguments);
          };
        })(name, fn);
      }
    }
  }
}

declare global {
  interface Window {
    [index: string]: () => any;
  }
}

Note: there are always simpler ways to prevent TypeScript from complaining:

Suppress an error:

// @ts-ignore
window[name] = (function(n, f) {

Use any keyword:

(window[name] as any) = (function(n, f) {

or

(<any>window[name]) = (function (n, f) {
yurzui
  • 205,937
  • 32
  • 433
  • 399