Reputation: 1381
I am trying to use globalThis
in TypeScript and I would like some suggestions on how to write it in a better way.
Current implementation is like this:
Create a file types/global.d.ts and add inside
interface Global {
foo: string
}
declare let foo: Global["foo"];
in tsconfig.json add
"files": [
"types/global.d.ts"
]
Then in order to set the value of foo
use
(globalThis as any).foo = "The value of foo"
What I don't like with this approach is first the boilerplate needed (but I think this cannot be avoided) and second the (globalThis as any).foo =
expression
Upvotes: 56
Views: 73098
Reputation: 2163
This is what worked for me using typescript
version 4.5.4
,
.d.ts
file with the needed types:export declare global { var foo: string; var goo: string; }
tsconfig.json
file (using files
property)Upvotes: 4
Reputation: 577
My answer is based on the one by Edward Casanova. I was about to edit it, but there are still quite a few differences to the code that works for me, plus I can now give some additional information on this.
This is based on TypeScript 4.3.5
// typings/globals.d.ts (depending on your tsconfig.json)
export {}
interface Person {
name: string
}
declare global {
var someString: string
var globalPerson: Person
}
This does not work without at least one export
(or import
) keyword. This turns this file into an ES module, which is necessary for this to work. You can export any of the statements or add an empty export {}
.
The code above adds types for the following handles:
someString
window.someString
globalThis.someString
globalPerson.name
window.globalPerson.name
globalThis.globalPerson.name
On the other side, the following is possible, but the result is different:
export {}
declare global {
let someLetString: string
const someConstString: string
}
This only adds types for the following handles:
someLetString
someConstString
As expected, you cannot assign any value to someConstString
. This might be useful for some older JS libraries that add the functionality to the global scope instead of exporting it. Libraries still can assign values to const
in this case because it's just a type, not a real const
. This const
is only known to TypeScript code. But be aware that let
and const
don't add properties to the global objects window
and globalThis
. So, var
might be the better choice here after all.
Upvotes: 27
Reputation: 24194
Applies to TypeScript 4.3+
Element implicitly has an
any
type because typetypeof globalThis
has no index signature. ts(7017)
declare global {
function myFunction(): boolean;
var myVariable: number;
}
globalThis.myFunction = () => true;
globalThis.myVariable = 42;
var
(do not use let
or const
).See the discussion on TypeScript issue 30139.
Traditionally, the way to specify a TypeScript declare-block in a Node.js context was as follows:
// Does not work as of October 2021 (TypeScript 4.3+)
declare global {
module NodeJS {
interface Global {
myFunction(): boolean;
myVariable: number;
}
}
}
Note that this error will be suppressed if the TypeScript setting noImplicitAny
is set to false
. It is recommended to enable noImplicitAny
for better type checking.
Upvotes: 97
Reputation: 49
but if you find alternative to
window.foo = 'value of foo'
then a simple solution is just
In typescript
other_var_name is the var holding other_var_value or an object or function
const foo = 'value of foo';
(global as any).foo;
work for me
Upvotes: 1
Reputation: 1064
Found a way. Perhaps a decent workaround
In a "global.d.ts" file at the root of your project, write the following
declare global {
var [propertyYouWantToAdd]: any; or typeof "anything you want. Perhaps import a class from a module";
//Make sure you use var instead of let or const, as it attaches to the global object.
}
Here's the reference in the docs
Upvotes: 3
Reputation: 2268
Using a combination of the other answers, here is what ended up working for me.
At the top of the TS file (or in a global typings file):
declare module globalThis {
let myObj: { foo: string };
}
globalThis.myObj = { foo: 'bar' };
Upvotes: 13
Reputation: 24314
TypeScript 3.4 introduces support for type-checking ECMAScript’s new globalThis
.
var x = 1
const y = 2
let z = 3
globalThis.x // ok
globalThis.y // should error, no property 'y'
globalThis.z // should error, no property 'z'
globalThis['x'] // ok
globalThis['y'] // should error, no property 'y'
globalThis['z'] // should error, no property 'z'
globalThis.Float64Array // ok
globalThis.Infinity // ok
declare let test1: (typeof globalThis)['x'] // ok
declare let test2: (typeof globalThis)['y'] // error
declare let test3: (typeof globalThis)['z'] // error
declare let themAll: keyof typeof globalThis
You can ready more about it in the documentation.
Upvotes: 4
Reputation: 1381
I finally ended up with the following solution in global.d.ts
interface Window {
foo: string
}
declare let foo: Window["foo"];
And used it in another file like
window.foo = "The value of foo"
Upvotes: 3
Reputation: 6529
You can use declaration merging in typescript to achieve this.
In your global.d.ts
file:
export declare global {
interface Window {
// add you custom properties and methods
foo: string
}
}
Now you can use Window.foo
without typescript warning you.
I wrote a mini blog about this on dev.to
Upvotes: 5