Globals 4 exercises
solution

Typing process.env in the NodeJS Namespace

Like before, the first step is to set up our declare global:


declare global {}

In order to decide what to put inside, let's examine process. Hovering over it shows us that it is NodeJS.ProcessEnv:


// hovering over `process`
process.env.MY_SOLUTION_ENV_VAR = "H

Loading solution

Transcript

0:00 Solution here, we know we're going to need access to that ambient context, declare global. We know that process.env here is NodeJS.ProcessEnv. That's interesting. If we try to just say interface ProcessEnv here, and we're going to add my solution environment variable here, then you notice that this doesn't seem to work.

0:24 We're inside a global context. This one is NodeJS.ProcessEnv. We've got the interface with the same name. Why isn't it working? If we look at process here, then inside here, we've got process.d.ts, which is coming from types/node. By the way, this is not by default included in the global namespace. It's not imported by lib either.

0:48 It's imported via, where is it, types/node just here, which is in devDependencies. Whenever you have @types here, then it gets put into the global ambient context. This is how we're able to get types for express, types for lodash, types for React, which don't ship with .d.ts files in their node modules.

1:09 What we've got here is inside declare module process, that's interesting, inside here, we've got a global which acts like a declare global. We've got namespace NodeJS. Namespace NodeJS, what is that doing? Everything inside this namespace sits in the global scope, but it sits in the global scope under that namespace.

1:36 This means that if you've got lots of libraries that are all conflicting with each other, maybe they have the same names, then they're not stepping on each other's declarations. This gives you a way to say, "OK, I own the namespace NodeJS, that's mine, you can't overwrite inside it," except you can.

1:57 What you can do is you can express this namespace NodeJS. Inside there, stick the interface ProcessEnv, and you get to declaration merge them. What it does is it just puts it at another level of nesting. You have to name this perfectly. If you go NodeJs with a lowercase s, then it doesn't work. It just declares another namespace with NodeJS. You can use NodeJS here.

2:24 What we can do is if we want to use this interface, we can say const whatever is NodeJS.ProcessEnv. That's how you access interfaces that are inside a namespace. You can't do this because it cannot find name ProcessEnv. Whereas if we say NodeJS.ProcessEnv, then we can do it.

2:46 Namespaces, node is the main place that they're used, but they're also used in various other external libraries that put things into the global. This is a solution that I use in pretty much all my applications, really. Again, you can't use type ProcessEnv because that redeclares it and you get this duplicate identifier.

3:07 Duplicate identifier coming from where? What are you talking about? The duplicate identifier is way off in the NodeJS namespace somewhere. If we take a look at this, in fact, here, we can't even pull that in, interface means you can declaration merge that. This is a way to type ProcessEnv variables.