DEV Community

a2br
a2br

Posted on

Get soft IntelliSense when using env vars

Here's a neat function to have some IntelliSense when getting environment variables: it helps, but doesn't prevent you from doing anything it doesn't expect. Go ahead and play with it in the TS playground!

// Will give IntelliSense for T, but accept U
export type LiteralUnion<T extends U, U = string> = T | (U & Record<never, never>);

// Your environment's map
type Env = {
    MONGO_AUTH: string;
    REDIS_PWD: string;
    JWT_SECRET: string;
    LOGDNA_KEY: string;
    HOSTNAME: string;
    NODE_ENV: "development" | "production";
    SUDO_PWD: string;
};
type RealEnv = Env & { [key: string]: string };

/**
 * @description Type-safe way to get env vars
 * @param key The data is located at `process.env[key]`
 * @param fallback Must not be `undefined` when used. To avoid throwing an error, put `""`
 */
export function env<K extends keyof Env, F extends LiteralUnion<Env[K]>>(
    key: LiteralUnion<K>,
    fallback?: F | (() => F)
): LiteralUnion<string extends Env[K] ? F : RealEnv[K] | F> {
    const data = process.env[key] as RealEnv[K] | undefined;
    if (data) {
        return data;
    } else {
        if (fallback === undefined) throw new EnvironmentVarError(key);
        if (typeof fallback === "function") fallback = fallback();
        return fallback;
    }
}
Enter fullscreen mode Exit fullscreen mode

Discussion (0)