cover

Type-safe env variables with Zod

By Dmytro Laptiev • October 15, 2025

cover
Best practices

Hello folks 👋

Let’s talk about something simple but important — environment variables.
They control everything from your database URL to your app’s behavior in different environments.

But here’s the catch:

Environment variables are always strings and often undefined.
That means you can easily end up with unexpected bugs — like using a string instead of a number or missing a required variable.

Let’s fix that with Zod 💪

Step 1: Define a Schema

With Zod, we can describe what our environment variables should look like and automatically validate them at runtime.

import { z } from 'zod'

const envSchema = z.object({
    PORT: z.coerce.number().min(1000).default(3000),

    ENV: z
        .union([z.literal('development'), z.literal('testing'), z.literal('production')])
        .default('development'),
})

export const env = envSchema.parse(process.env)

Step 2: Parse and Use It

Now when we created a env.ts file we can easily use environment variables.

import { env } from 'env'

console.log(env.PORT);