Typescript: Unable to substitute console with a dummy class

Created on 7 Feb 2017  路  5Comments  路  Source: microsoft/TypeScript




When running in a browser, window.console may be unavailable while the browser's developer tools are not opened. Calls to window.console may therefore cause errors. To circumvent this, a common approach is to assign a dummy class with the required methods to catch this situation. However, after the introduction of the readonly modifier, this approach no longer works, and instead produces a compiler error.

TypeScript Version: 2.1.1 / nightly (2.2.0-dev.201xxxxx)

Code

if (typeof window.console === "undefined") {
    // Define a dummy window.console if not debugging
    window.console = <Console>({
        debug: (message ?: string, ...optionalParams: any[]) => {},
        error: (message?: any, ...optionalParams: any[]) => {},
        info: (message ?: any, ...optionalParams: any[]) => {},
        log: (message?: any, ...optionalParams: any[]) => {},
        warn: (message?: any, ...optionalParams: any[]) => {}
    });
}

Expected behavior:
window.console is set to the dummy class when the console is not available and uses the browser's console otherwise

Actual behavior:
TS2540: Cannot assign to 'console' because it is a constant or a read-only property.

Question

Most helpful comment

console is a readonly property of Window. Try casting window to any. This erases all type info, so it should be allowed.

if (typeof window.console === "undefined") {
    // Define a dummy window.console if not debugging
    (<any>window).console = <Console>({
        debug: (message ?: string, ...optionalParams: any[]) => {},
        error: (message?: any, ...optionalParams: any[]) => {},
        info: (message ?: any, ...optionalParams: any[]) => {},
        log: (message?: any, ...optionalParams: any[]) => {},
        warn: (message?: any, ...optionalParams: any[]) => {}
    });
}

All 5 comments

Try this

declare global {
  interface Window {
    console: Console;
  }
}

@aluanhaddad I assume your suggestion should go into my .ts file? If that's so, then unfortunately, your solution doesn't work, as I get

TS2669: Augmentations for the global scope can only be directly nested in external modules or ambient module declarations.

in addition to the previous error.

console is a readonly property of Window. Try casting window to any. This erases all type info, so it should be allowed.

if (typeof window.console === "undefined") {
    // Define a dummy window.console if not debugging
    (<any>window).console = <Console>({
        debug: (message ?: string, ...optionalParams: any[]) => {},
        error: (message?: any, ...optionalParams: any[]) => {},
        info: (message ?: any, ...optionalParams: any[]) => {},
        log: (message?: any, ...optionalParams: any[]) => {},
        warn: (message?: any, ...optionalParams: any[]) => {}
    });
}

@alitaheri That does the trick. Thank you.

@aluanhaddad I assume your suggestion should go into my .ts file? If that's so, then unfortunately, your solution doesn't work, as I get

TS2669: Augmentations for the global scope can only be directly nested in external modules or ambient module declarations.
in addition to the previous error.

My approach presumed that you were using external modules, for which I apologize. You can use

interface Window {
  console: Console;
}

instead.

That said, if you otherwise want to preserve the readonlyness of window.console then @alitaheri's solution is the way to go.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Gaelan picture Gaelan  路  231Comments

blakeembrey picture blakeembrey  路  171Comments

kimamula picture kimamula  路  147Comments

RyanCavanaugh picture RyanCavanaugh  路  205Comments

rwyborn picture rwyborn  路  210Comments