Types You Don't Control 12 exercises

Adding Types to the Global Scope

The first thing we'll do is create a new window.d.ts declaration file in the src directory.

We need this file to be treated as a script in order to access the global scope, so we will not include the export keyword.

Inside the file, we'll create a new interface named Window that exten

Loading solution


00:00 Okay, this is cool. What we're going to do is we're going to create a declaration file. We're going to call it window.d.ts. In fact, just to disambiguate it, we're going to call it window whatever cool man.d.ts. It doesn't matter what we call this file. What we're doing here is we're going to put something into the global scope,

00:17 because we know that index.ts here, if we look at window, this is an interface in the global scope. And we know that if we declare two interfaces with the same name, so we have interface, wow, interface, wow. Let's say we have an ID string on this one and name string on this one.

00:34 And then we go, okay, const wow is going to be wow. Ooh, there we go. And we basically need to specify ID and name on it. This means that, ah, this is really cool. It means that we don't need to do anything else to it. We just specify an interface in the same scope and boom, we're ready to go.

00:54 So we can access the global scope by, basically we're in the global scope now. If we were to do like an export empty object, then this would be treated as a module, not a script. So we need it to be treated as a script in order to access the global scope. And we can say interface window,

01:14 and now we can add whatever we want to inside here. So let's add a debug object. And now we're getting an error, or like it's being inferred properly. Yes, fantastic. We've got window.debug and we need a get state function. Let's just say it returns void. And now state is going to be of type void

01:32 because get state is now available. And we actually want it to return an ID string here. Whoops, I'm a bit zoomed in here just so you can see everything. Wonderful, look at this. So now then, if we look at state, it's being inferred properly because we have interface window declared here.

01:50 Note that if I added this interface window into our TS file, it wouldn't work. That's because these interfaces are not in the same scope. This is not in a global scope, but it would work if I put it in a declare global.

02:08 So now declare global interface window, it's now going to work because it's in the global scope. And I'm pretty sure too, if I said, let me remove this interface. If I said export interface window, it also wouldn't work because this interface window is now being treated as like an export from a module.

02:28 So we need to remove that export, stick it in the global scope, bam. And now it's working. So this is the best way that you can add types to window, which is really important when you're working in the DOM and you've got external scripts being loaded. I obviously don't recommend like flooding your globals

02:46 with JavaScript variables and things like that, but if you do have to do it, if an external script is hooking something in there, you need to make sure that the access to it is type safe. And this is the best way of doing it.