Search code examples
javascripttypescriptglobal-variables

TypeScript - declare truly global variable to access directly, no window, global or globalThis


I want to pass some environment variables to a front-end app. They are passed via replace as part of the build process, so for example: if (ENV_IS_PRODUCTION) { ... } will evaluate to: if (false) { ... } in the compiled bundle (so it can be stripped completely by the minifier).

Now I need some way to tell TypeScript that ENV_IS_PRODUCTION is a boolean. I want to use it directly, window.ENV_IS_PRODUCTION would evaluate to window.false so it's not an option.

The furthest I came with it is to declare it locally:

declare const ENV_IS_PRODUCTION: boolean;

But I have no idea how to declare it globally. I tried putting the above local definition into globals.d.ts but it doesn't work. And again, I cannot use window, global, or globalThis. It has to be accessed directly as a variable, without having to import it and without using window/global.


Solution

  • Actually, it turns out the local definition put into globals.d.ts should work. I just had some problems with VS Code not picking it up (worked after the restart, but I probably didn't notice as Eslint gave an error separately - which I still haven't solved but it's rather minor).

    So the solution, in this case, is to simply put this in globals.d.ts:

    declare const ENV_IS_PRODUCTION: boolean;
    

    Update:

    The Eslint error that caused the confusion was because Eslnt doesn't seem to recognize types defined like this. The solution is to disable no-undef rule for all TypeScript files - it is redundant anyway, as tsc will not allow an undefined variable anyway. https://github.com/typescript-eslint/typescript-eslint/issues/342

    Update 2:

    I will add that another reason it didn't work for me initially is that there appears to be something off with globals.d.ts When I had this definition, and a declaration about Window object, in one globals.d.ts - it didn't work too. I settled on using compilerOptions.typeRoots and put the type files there instead of using globals.d.ts and it's working fine.

    So the best solution is:

    tsconfig.json

    {
      ...
      "compilerOptions": {
        ...
        "typeRoots": [
          "./node_modules/@types",
          "./src/types"
        ]
       }
    }
    

    src/types/env.d.ts

    declare const ENV: {
      IS_PRODUCTION: boolean
    };