I setup global namespaces for my objects by explicitly setting a property on window
.
window.MyNamespace = window.MyNamespace || {};
typescript prevent accessing object without assigning type that has the desired property or
already assigned to any
so you can use optional chaining window?.MyNamespace = 'value'
.
Most of the other answers are not perfect.
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 {
myNamespace?: 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 myNamespace
(the property of window).
For those who want to set a computed or dynamic property on the window
object, you'll find that not possible with the declare global
method. To clarify for this use case
window[DynamicObject.key] // Element implicitly has an 'any' type because type Window has no index signature
You might attempt to do something like this
declare global {
interface Window {
[DyanmicObject.key]: string; // error RIP
}
}
The above will error though. This is because in Typescript, interfaces do not play well with computed properties and will throw an error like
A computed property name in an interface must directly refer to a built-in symbol
To get around this, you can go with the suggest of casting window
to <any>
so you can do
(window as any)[DynamicObject.key]
The accepted answer is what I used to use, but with TypeScript 0.9.* it no longer works. The new definition of the Window
interface seems to completely replace the built-in definition, instead of augmenting it.
I have taken to doing this instead:
interface MyWindow extends Window {
myFunction(): void;
}
declare var window: MyWindow;
UPDATE: With TypeScript 0.9.5 the accepted answer is working again.
First you need to declare the window object in current scope.
Because typescript would like to know the type of the object.
Since window object is defined somewhere else you can not redefine it.
But you can declare it as follows:-
declare var window: any;
This will not redefine the window object or it will not create another variable with name window
.
This means window is defined somewhere else and you are just referencing it in current scope.
Then you can refer to your MyNamespace object simply by:-
window.MyNamespace
Or you can set the new property on window
object simply by:-
window.MyNamespace = MyObject
And now the typescript won't complain.