Define global namespace/variable within a TypeScript module

10,941

Solution 1

The solution is to declare namespace in global.

declare global {
  namespace foo.blah {
     function baz() {
       console.log('hello');
     }
  }
}

Solution 2

When you add the import, you switch from internal modules to external ones, as the spec says:

In external modules, relationships between files are specified in terms of imports and exports at the file level. In TypeScript, any file containing a top-level import or export is considered an external module.

http://www.typescriptlang.org/Handbook#modules-going-external

The philosophy behind external modules is to avoid global objects, why don't you create a new module with foo.blah (and all the stuff you need) and import it as TypeScript expects it?

Share:
10,941
Jesse
Author by

Jesse

Updated on June 17, 2022

Comments

  • Jesse
    Jesse about 2 years

    In TypeScript I can define a global/top-level namespace and use it in another file like so:

    namespace foo.blah {
        export function baz() {
            console.log('hello');
        }
    }
    

    And in another file, this works:

    foo.blah.baz();
    

    However, if I then import something from another module:

    import Thing from 'boo';
    
    namespace foo.blah {
        export function baz() {
            console.log('hello');
        }
    }
    

    Suddenly my whole file is a module, the foo.blah namespace is local, not global, and the foo.blah.baz() call in the other file fails. export namespace ... just causes the namespace to become part of the module's export, not a global.

    Is there a way to write a TypeScript file which imports from other modules but also defines global/top-level symbols?

    At the moment I'm doing this:

    import Thing from 'boo';
    import * as $ from 'jquery';
    
    namespace foo.blah {
        export function baz() {
            console.log('hello');
        }
    }
    
    $.extend(true, window, {foo});
    

    Which works, but the TypeScript compiler still can't see that foo.blah... exists as a global in other files.

    (The file is the entry point for Webpack, and I'm trying to import things from other modules in the Webpack bundle and assign them to globals so they can be used in <script> tags on the page.)

  • Jesse
    Jesse over 8 years
    As I said, I'm trying to define global variables for use in <script> tags inside the page, using what is exported by other modules. (The application is over a decade old and I'm trying to incrementally move it to pure TypeScript.)
  • MartyIX
    MartyIX over 8 years
    If you want to slowly migrate then why don't you use .d.ts files (e.g. github.com/DefinitelyTyped/DefinitelyTyped/blob/master/ace/…‌​) and then just use references like this ///<reference path="relative/path/to/file.d.ts" />?
  • Parzh from Ukraine
    Parzh from Ukraine about 2 years
    This yields compiler error An implementation cannot be declared in ambient contexts.. The declare keyword designates an ambient context, which means that the given entity does not exist in runtime, only in TypeScript.