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;
}
}
Top comments (0)