Skip to content

Env variables on node with Typescript

Why have types and default values on env variables?

When working in a node app using Typescript and env variables if you try to access your variables using process.env.variableName you will realize that the type is always string | undefined, if you need a different type or manipulate the variable you will need to do this on every place where you use that variable which can be repetitive and inefficient, instead we could create config file with our env variables, so we could do these manipulations and parsings in the same place and just import the final output we need

Solution

We are going to create a config file inside our project that will get our env variables from env file and parse them or add default values needed

Env variables

We will use the next env variables stored in the .env file for testing

NODE_ENV=development
PORT=3000
NUMBER_VARIABLE=1
ARRAY_VARIABLE=name,email,password
CAPITALIZED_VARIABLE=john doe

Config folder

Create a config folder inside the src of you app, here we will add sub folder dividing the env variables, we do this to have a better organization of the variables. Don't forget to install @types/node and add "types": [ "node" ] to the compilerOptions section of your tsconfig.json, or you will need to assert the type of each env variable to string like this process.env.NODE_ENV as string

// src/config/express/index.ts

// Interface defining express env variables types
interface ExpressEnvVariables {
    port?: number;
    env: string;
}

// Express env variables
const expressEnvVariables: ExpressEnvVariables = {
    // Parse port to int, set value to 3000 if no port was defined on env variables
    port: parseInt(process.env.PORT) || 3000,
    env: process.env.NODE_ENV,
};

export { expressEnvVariables };

// src/config/test/index.ts

// Interface defining test env variables types
interface TestEnvVariables {
    numberVariable: number;
    arrayVariable: string[];
    capitalizedVariable: string;
}

// Test env variables
const testEnvVariables: TestEnvVariables = {
    // Parse number variable to int
    numberVariable: parseInt(process.env.NUMBER_VARIABLE),
    // Transforms array variable to array of strings
    arrayVariable: process.env.ARRAY_VARIABLE.split(","),
    // Capitalize variable
    capitalizedVariable: process.env.CAPITALIZED_VARIABLE.charAt(0).toUpperCase() + process.env.CAPITALIZED_VARIABLE.slice(1),
};

export  { testEnvVariables };

How to use variables on config folder

Let's use the following express app to show how to import and use variables on config file, as you can see you are able to see the type of the variables thanks to the interfaces used

// ./index.ts
import 'dotenv/config'

import express, { Application, Request, Response } from "express";
import { expressEnvVariables } from "./src/config/express";
import { testEnvVariables } from "./src/config/test";

// New express application instance
const app: Application = express();

/**
 * Health route
 */
app.get("/health", (req: Request, res: Response) => {
    res.status(200).send("working")
})

/**
 * Env variables route
 */
app.get("/env-variables", (req: Request, res: Response) => {
    const  numberVariable = testEnvVariables.numberVariable;
    const  capitalizedVariable = testEnvVariables.capitalizedVariable;
    const  arrayVariable = testEnvVariables.arrayVariable;

    res.status(200).send({ numberVariable, capitalizedVariable, arrayVariable })
})

/**
 * Begin listening on port selected
 */
app.listen(expressEnvVariables.port, () => {
    console.log(`Server is running on port ${expressEnvVariables.port}...`);
});

Now you are able to parse and define the type of your env variables