When we try to access our environment variables from process.env
object in the Node.js and TypeScript application, we don't get auto-completion by default.
Because TypeScript has no idea what environment variables we have inside process.env
object. But you can change this behavior by adding types to it.
How to Define Types To process.env For Auto-completion
These are the 3 simple steps to add types to environment variables (process.env
) in Node.js application:
- Step 1: Create a type declaration file.
- Step 2: Extend
process.env
type by creatingProcessEnv
interface. - Step 3: Include the type declaration file in the
tsconfig.json
file.
By doing so, TypeScript will know about your environment variables and get suggestions whenever you try to access them in your project.
Step 1: Creating a Type Declaration File
A type declaration file in TypeScript is a file that contains type information about JavaScript files. Usually, type declaration files end with .d.ts
extensions.
It serves as a way to provide type annotations for existing JavaScript code that doesn't have explicit type information.
Therefore to create a type declaration file, you have to create a file that ends with .d.ts
extension. You can give any name to this file, the name doesn't matter.
|-- node_modules
|-- types
|-- env.d.ts
|-- .env
|-- server.ts
|-- package-log.json
|-- package.json
|-- tsconfig.json
Here I am creating a env.d.ts
file inside a types folder. This is the file structure of my project.
Step 2: Extending process.env with Custom Types
To add custom types to the process.env
object you have to create ProcessEnv
interface inside your type declaration file. You must name this interface as it is. A different name won't work.
It will contain all the environment variables. You have to declare it inside the NodeJS
namespace.
declare global {
namespace NodeJS {
interface ProcessEnv {
API_KEY: string
PORT?: number
NODE_ENV: 'development' | 'production'
}
}
}
export {}
Declare a global NodeJS
namespace in the env.d.ts
file. This namespace will contain the ProcessEnv
interface with all the environment variables.
I have added 3 properties to this interface: API_KEY, PORT, and NODE_ENV
Because I have these 3 environment variables in my .env
file. You have to include all of your variables in this way.
You can also make environment variables optional by adding "?" at the end of their names. Here, the PORT
is an optional variable.
Don'f forget to export an empty object. It will make this file as a module. Without it, this interface won't work.
Also Read: Power of declare Keyword in TypeScript: Complete Guide
Step 3: Connecting The Declaration File with Node.js
Creating the declaration file and adding ProcessEnv
interface won't add types to the process.env
object. You also have to let TypeScript know about it.
You can connect this file to TypeScript by adding its path in the tsconfig.json
file.
{
"compilerOptions": {
// ...
"typeRoots": ["types/env.d.ts", "node_modules/@types"]
}
}
Add the path of your type declaration file in the typeRoots
array along with the @types
folder from the node_modules
folder.
Congratulations, you have successfully added your custom types for process.env
object. Now you will get auto-completion from TypeScript for your environment variables.
Also Read: Add Properties in TypeScript Based on Another Property Value
Loading and Using Type-Safe Environment Variables
You have to load environment variables to a Node.js project to access them from the process.env
object. You have to use the dotenv package for this.
Install dotenv
package with the following command:
npm install --save dotenv
Now you have to import and initialize this package to load .env
file to your project.
import 'dotenv/config'
console.log(process.env.NODE_ENV)
// production
You can import and initialize this package using import 'dotenv/config'
in your TypeScript file. This will load your .env
file from the root of your project by default.
Now whenever you want to access your environment variables from process.env
object, TypeScript will give you suggestions.
Also Read: TypeScript Type vs. Interface: Which One Should You Use?
Handling Undefined and Optional Environment Variables
If you declare any of your environment variables as optional, you should perform if
checks before using their values in production. Otherwise, you might get errors if they are not available or undefined.
TypeScript could show your error messages if you try to access optional values without using any check.
import 'dotenv/config'
if (process.env.PORT) {
console.log(process.env.PORT)
// 3000
}
Here the PORT
environment variable is optional. Therefore, I am checking if this variable has any value or not using the if
statement.
const PORT = process.env.PORT || 3000
console.log(PORT)
// 3000
You can also set default values for your optional variables. Here I am setting 3000
as default if the process.env.POR
T is undefined.
That's it. This is how you can add types for your environment variable in TypeScript for your Node.js project. You will get type safety and auto-completion from TypeScript.
Also Read: Mastering Type Guards in TypeScript: Making Your Code Safer