Load Env is built with TypeScript-first design, providing comprehensive type safety at both compile-time and runtime. Every function validates input and guarantees type-correct output, eliminating an entire class of configuration errors.
import { envInt } from "@axel/load-env"try { const value = envInt("PORT")} catch (error) { if (error instanceof TypeError) { // Variable exists but has wrong type console.error(error.message) // $PORT is not a number: abc console.error(error.cause) // Original invalid value }}
Use this distinction to provide better error messages: Error means configuration is missing, TypeError means configuration is invalid.
The library uses internal validation functions that you can understand from the source:
Boolean validation (toBool)
// Accepts (case-insensitive):// - true, false// - 1, 0// - yes, no// - on, offexport function toBool(key: string, value: string): boolean { const lower = value.toLowerCase() if (["true", "1", "yes", "on"].includes(lower)) return true if (["false", "0", "no", "off"].includes(lower)) return false throw new TypeError(`${key} is not a boolean: ${value}`)}
Enum validation (isEnum)
export function isEnum<T extends string[]>( value: string, values: T,): value is T[number] { return values.includes(value as T[number])}
UUID validation (isUuid)
// Validates RFC 4122 UUID formatexport function isUuid(value: unknown): value is UUID { if (typeof value !== "string") return false return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test( value, )}
import { envEnum, envUrl, envString } from "@axel/load-env"const NODE_ENV = envEnum( "NODE_ENV", ["development", "production"] as const, "development",)if (NODE_ENV === "production") { // TypeScript knows this is production const dbUrl = envUrl("DATABASE_URL") // Required in production} else { // TypeScript knows this is development const dbUrl = envUrl("DATABASE_URL", new URL("postgresql://localhost/dev"))}
import { maybeEnvString } from "@axel/load-env"const apiKey = maybeEnvString("API_KEY")function requireApiKey(key: string | undefined): asserts key is string { if (!key) { throw new Error("API_KEY is required for this operation") }}requireApiKey(apiKey)// TypeScript knows apiKey is string hereconsole.log(apiKey.length)
import { envUrl, envString } from "@axel/load-env"// Load and validate earlyexport const DATABASE_URL = envUrl("DATABASE_URL")export const JWT_SECRET = envString("JWT_SECRET")// If we get past initialization, these are guaranteed validexport async function connectDatabase() { // DATABASE_URL is known to be a valid URL return connect(DATABASE_URL)}