Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript - Attach module/namespaces to window

I've built a lot of APIs and applications using ES2015, but I am not used to the best practices in TypeScript yet, so maybe you can help me. Let's say I am building an API/SDK for a shop. The goal is that the user includes my js file and accesses the shop and its namespaces via the window object, much like it is possible with angular and other libs as well.

window.shop.init();
window.shop.cart.get();
window.shop.cart.set();
window.shop.cart.clear();

In ECMAScript 2015, I would write my methods like get and set, import them in my main file and extend the shop object and finally the global object.

// in my cart.js namespace file
export {get} from './get';

// in my shop.js
import * as cart from './cart';

global.shop = {
    cart
}

Being a good approach for namespacing in ES2015, it feels kinda wrong in TypeScript having all those module and namespace keywords.

I basically want to achieve the same in TS. I tried things like the following, but with no success.

module shop {
    export const cart = {...}
}

(<any>window).shop = shop;

or

namespace shop {
    // ...
}

(<any>window).shop = shop;

There where some tutorials claiming that a module is automatically attached to the global/window object, but that did not happen for me.

I am using TypeScript 1.8.10. Any help is greatly appreciated!

like image 904
Rico Herwig Avatar asked May 25 '16 07:05

Rico Herwig


2 Answers

There where some tutorials claiming that a module is automatically attached to the global/window object, but that did not happen for me.

Maybe because the code of your namespace is in an (ES6) module instead of in a script? The differences between scripts and modules are detailed here.

The code below makes a global variable shop in the browser if it is loaded as a script, ie with a tag <script src="shop.js"> (or you can concatenate this file with other JavaScript files, for example with uglifyjs).

// File shop.ts
namespace shop {
    export const cart = { /* ... */ }
}

If your code is loaded as an ES6 module (ie with the help of Webpack, SystemJS, RequireJS or other), your solution is valid:

(<any>window).shop = shop;
like image 167
Paleo Avatar answered Sep 29 '22 14:09

Paleo


The answer by @paleo is not perfect. It just suppress the type inference for shop.

I also encounter the similar problem this morning. I tried so many "solutions" on SO, but none of them produce no type error absolutely and enable triggering type jumping in IDE(webstorm or vscode).

Finally, from here

https://github.com/Microsoft/TypeScript/issues/3180#issuecomment-102523512

, I find a reasonable solution to attach typings for global variable which acts as interface/class and namespace both.

Example is below:

// typings.d.ts
declare interface Window {
    shop?: MyNamespace & typeof MyNamespace
}

declare interface MyNamespace {
    somemethod?()
}

declare namespace MyNamespace {
    // ...
}

Now, the code above merges the typings of namespace MyNamespace and interface MyNamespace into the global variable shop(the property of window).

like image 20
e-cloud Avatar answered Sep 29 '22 14:09

e-cloud