Access `global` as a type
blakeembrey opened this issue ยท 9 comments
Since https://github.com/Microsoft/TypeScript/wiki/What%27s-new-in-TypeScript#augmenting-globalmodule-scope-from-modules it's been possible to augment the global
from a module. However, in TypeScript definitions (such as dom.d.ts
or node.d.ts
) we're left to create our own "globals". This results in two issue:
- inconsistency with what is actually the global namespace
- requiring the declaration of global types multiple times in case it's used as a "real global" or from
window.
(browsers) orglobal.
(node)
Instead of this, it'd be really nice to access TypeScript's global
as a type. For instance, in dom.d.ts
we could do:
declare var window: global
Or in node.d.ts
:
declare var global: global
I couldn't see any previous issues, but it's partially related to things like #12902 - the difference though is that those issues seems to be tracking adding variables to the TypeScript global scope whereas this would be using the global scope as a type to define these variables themselves.
This is similar to #10050. Having a referenceable global
type would do away with some painful duplication in declaration files. An additional scenario is sandboxed globals, described in #10050 (comment).
@mhegazy Sorry, I read #12902 (comment) as a comment meaning it was really just a lib.d.ts
change (e.g. declare var global: Window
). If it is instead adding a real global type that mirrors TypeScript's "global" state and can be used in a type position for module authors I'm happy to close this issue.
@mhegazy Sorry, I read #12902 (comment) as a comment meaning it was really just a lib.d.ts change (e.g. declare var global: Window).
I think this is the feeling when we looked at this first. but I would expect users will have a similar request like yours. i would expect ppl wanting to do typeof global
and be able to get things in declare global {...}
blocks as well as declarations in the global scope.
If it is instead adding a real global type that mirrors TypeScript's "global" state and can be used in a type position for module authors I'm happy to close this issue.
I am fine lumping the two together, or keeping them separate. I would expect we need to do both if the proposal moves forward in the committee.
We just ran in to this as well. We are handcoding typescript definitions for a legacy js library in the hope of pushing it to @types. We have multiple internal modules. One of the modules have a global variable X. And other have a variable X inside our common namespace Y. Now when the d.ts file of a third module want to refer the global X from inside our common namespace Y, there is no way right now. Any help on this?
@nolakara the need for a way to fully qualify a name has been discussed previously in #983. we then concluded that there was not a pressing need for this with modules and aliasing support. The recommendation for this case is to alias the global variable outside of your namespace and use the alias instead, e.g.:
import global_x = x;
namespace Y {
export class x { }
var local: x;
var global: global_x;
}
One way I resolved this was to create a layer from global to register globals. In namespace "A" I register global "x". "y". "z" properties (i.e. namespace A { export var x: ExpectedType; } A.x = x;
), or even interfaces IX, IY, IZ, etc. In namespace A.B, or A.B.C, etc.,, I register all other types. This means I can always access A.x or A.IX (globals), or A.B.x (local types), etc. To make it easier I created a separate namespace for the globals, such as namespace AGlobals { export var globalx = x; }
then you could do namespace A { export var x = AGlobals.globalx; }
.
Example: https://goo.gl/JreGBg
var x = 1;
interface ISomeType { y: number; }
namespace AGlobals {
export var globalx = x;
export type globalISomeType = ISomeType;
}
namespace A {
export var x = x;
export type ISomeType = AGlobals.globalISomeType; // (OR use only AGlobals.globalISomeType instead)
export namespace B {
export var x = 2;
export interface ISomeType { z: number; }
var o: A.ISomeType; // (OR AGlobals.globalISomeType - depends on what you want)
export function doSomething() {
A.x = A.B.x;
o.y = x;
}
}
}
There is another way to access globals using eval
(or Function(...)
) like this:
var x = 1;
function test() { var x = 2; return eval.call(null, "x"); }
test(); // returns 1 because eval is now called in the global scope.
Using new Function("return x;")
also works instead of eval.call()
.
That assumes, of course, you are not trying to access a type (like an interface), and you will have to explicitly specify the expected type manually.
Random update: We pretty much know we want to do this (and talked about it when we added import
types), we're just waiting for https://github.com/tc39/proposal-global (the proposal referenced in #12902) to stabilize with a name for the global-thing, so we can use the same name for the type lookup.
This is now supported by using typeof globalThis
in a type position.