Heinrich Ulbricht
Heinrich Ulbricht

Reputation: 10372

How to create global namespace/class in TypeScript that can be used in plain JavaScript?

My TypeScript and plain JavaScript code need to share a namespace and some data. TypeScript should "prepare" a namespace, external JS provides data, TypeScript processes it.

The context is an Angular 2 application. The loading order is:

  1. Angular 2 app with its JavaScript starts
  2. a custom external JavaScript file is dynamically loaded from an external source (JSONP style)
  3. Angular 2 app does further processing on the data generated by the loaded JS file

Currently in the external JavaScript file I'm doing something like this:

if (typeof Blog === 'undefined')
{
    Blog = {
        Posts: []
    }
}
// ...
Blog.Posts.push(post);

In my Angular 2 app this JavaScript file is being dynamically loaded and the value then accessed like this:

declare var Blog: any;
...
let firstPost = Blog.Posts[0];

This works, I can access data placed by the external JS.

Now I want to keep the JavaScript part as minimal as possible. So I want to move the declaration of Blog and Posts to TypeScript, preferably so that it can be used there in a strongly typed fashion.

So I wish my JavaScript looked like this:

// ...
Blog.Posts.push(post);

Note the missing declaration of Blog. I tried something like this in TypeScript:

declare var Blog: BlogClass; // <- this is probably wrong, can be changed to anything necessary to make it work...
// ...
Blog = new BlogClass();

But apparently its not that easy. My Angular 2 app dies on me with a generic error message. The error is caused by Blog = new BlogClass().

Any hints on how to solve this?

Upvotes: 0

Views: 1271

Answers (1)

artem
artem

Reputation: 51579

declare means that the thing being declared must be defined somewhere else.

declare var Blog: BlogClass;

does not produce any code in the resulting javascript, so this assignment

Blog = new BlogClass(); 

fails at runtime because Blog does not exist.

When you remove declare, this line appears in the generated code:

var Blog;

However, it does not necessarily create var Blog in global scope - when you compile typescript code as modules, it will be created inside a module and will be inaccessible to external javascript code, unless you go through the route of exporting it from typescript module and importing that module in your javacsript code.

The simplest (but a bit dirty) way to make sure that an object is created in global scope is to do that explicitly:

(window as any).Blog = new BlogClass();

Upvotes: 2

Related Questions