Setting up typed environment variables in your project

codewithonye

code-with-onye

Posted on August 31, 2024

Setting up typed environment variables in your project

Have you ever found yourself struggling to remember the exact name of an environment variable you set? Perhaps you only recall that it starts with "N"? In such situations, wouldn't it be great to have autocompletion for your environment variables?

In this article i will show you how to set up typed environment variables in your next project, making your development process more efficient and error-resistant.

Why Type Your Environment Variables?

Typing your environment variables can:

  1. Save time by providing autocompletion
  2. Prevent errors caused by typos or incorrect variable names
  3. Ensure all required variables are present
  4. Provide type safety for your application

Now let's explore the steps to set up

1. Set Up Your Environment Variables
First, create a .env file in your project root with your environment variables:

NODE_ENV=development
DB_HOST=localhost
DB_USER=user1
DB_PASSWORD=test2345
DB_NAME=test
DB_PORT=5432
DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}
SECRET_KEY=12372972979263737972
PAYSTACK_SECRET_KEY=sk_test_7393695925636
Enter fullscreen mode Exit fullscreen mode

2. Install Dependencies
Install the necessary packages:

npm install dotenv dotenv-expand zod
Enter fullscreen mode Exit fullscreen mode

3. Create the Environment Configuration File
Create a file named env.ts in your utils folder:

import { config } from "dotenv";
import { expand } from "dotenv-expand";
import { ZodError, z } from "zod";

const stringBoolean = z.coerce
  .string()
  .transform((val) => val === "true")
  .default("false");

const EnvSchema = z.object({
  NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
  DB_HOST: z.string(),
  DB_USER: z.string(),
  DB_PASSWORD: z.string(),
  DB_NAME: z.string(),
  DB_PORT: z.coerce.number(),
  DATABASE_URL: z.string().url(),
  DB_MIGRATING: stringBoolean,
  DB_SEEDING: stringBoolean,
  SECRET_KEY: z.string().min(32),
  PAYSTACK_SECRET_KEY: z.string().startsWith("sk_"),
});


export type EnvSchema = z.infer<typeof EnvSchema>;
expand(config());

try {
  EnvSchema.parse(process.env);
} catch (error) {
  if (error instanceof ZodError) {
    const missingVars = error.issues.map((issue) => issue.path[0]).join(", ");
    throw new Error(`Missing or invalid environment variables: ${missingVars}`);
  }
  throw error;
}


export default EnvSchema.parse(process.env);
Enter fullscreen mode Exit fullscreen mode

Using Your Typed Environment Variables

Now you can import and use your typed environment variables in your application:

import env from './utils/env';

console.log(env.DB_HOST);
console.log(env.DATABASE_URL);
Enter fullscreen mode Exit fullscreen mode

By following these steps, you've set up a robust system for managing your environment variables with type safety and validation.

This approach will help you catch configuration errors early and make your development process smoother.

Thanks for reading✌️

💖 💪 🙅 🚩
codewithonye
code-with-onye

Posted on August 31, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related