Hey there, fellow developers! Today, I want to share something that tripped me up when I first started using TypeScript: dealing with global variables. Specifically, I’m going to show you how to work with global variables that are defined outside your TypeScript code.
Let’s set the scene. Imagine you’re building a web app where you need to pass some data from your server-side code to your client-side TypeScript. A common way to do this is by using a global variable. Here’s what that might look like in your HTML:
<script>
window.__INITIAL_DATA__ = {
userID: "536891193569405430",
};
</script>
Simple enough, right? But here’s where it gets tricky. If you try to use this __INITIAL_DATA__
in your TypeScript file, you’ll run into an error:
// Error: Property '__INITIAL_DATA__' does not exist on type 'Window & typeof globalThis'
const initialData = window.__INITIAL_DATA__;
Don’t worry, though! I’ve got three ways to fix this, each with its own pros and cons.
Method 1: The Quick and Dirty – Type Assertion
The fastest way to make TypeScript stop complaining is to use a type assertion:
const initialData = (window as any).__INITIAL_DATA__;
This tells TypeScript, “Trust me, I know what I’m doing.” It’s quick, but it’s not very safe. You lose all type checking for initialData
.
If you want to be a bit safer, you can define the shape of your data:
type InitialData = {
userID: string;
};
const initialData = (window as any).__INITIAL_DATA__ as InitialData;
Now you can use initialData.userID
safely. But remember, this doesn’t guarantee the data will actually be there at runtime!
Method 2: Declare a Global Variable
A more TypeScript-y way is to declare the global variable:
declare var __INITIAL_DATA__: InitialData;
const initialData = __INITIAL_DATA__;
// or
const initialData = window.__INITIAL_DATA__;
This tells TypeScript, “Hey, there’s going to be a variable called __INITIAL_DATA__
with this shape.”
Pro tip: If you’re using modules (files with import
or export
), you’ll need to use declare global
:
declare global {
var __INITIAL_DATA__: InitialData;
}
If you’re using this in multiple files, consider creating a globals.d.ts
file to declare all your global variables in one place.
Method 3: Augment the Window Interface
The most TypeScript-native approach is to add your variable to the Window
interface:
interface Window {
__INITIAL_DATA__: InitialData;
}
const initialData = window.__INITIAL_DATA__;
This tells TypeScript that window
should have an __INITIAL_DATA__
property.
Again, if you’re using modules, you’ll need:
declare global {
interface Window {
__INITIAL_DATA__: InitialData;
}
}
And there you have it! Three ways to handle global variables in TypeScript. Each has its place:
- Type assertions are quick but least safe.
- Declaring global variables is a good middle ground.
- Augmenting the Window interface is the most “correct” but requires a bit more setup.
Remember, TypeScript is here to help us catch errors, but it’s up to us to use it correctly. Happy coding!