Skip to content

Instantly share code, notes, and snippets.

@MikuroXina
Last active July 27, 2022 14:55
Show Gist options
  • Select an option

  • Save MikuroXina/270c83f38dc981b16f8ac6eaea8e3103 to your computer and use it in GitHub Desktop.

Select an option

Save MikuroXina/270c83f38dc981b16f8ac6eaea8e3103 to your computer and use it in GitHub Desktop.
Extraction of environmental variables for Node.js.
/// 必要な環境変数名を可変長引数に渡すと, 環境変数ごとに対応した値が入ったオブジェクトを返す.
///
/// 対応した環境変数が定義されていない場合は `defaults` に設定した値へとフォールバックする.
///
/// # 例外
///
/// 対応した環境変数が定義されておらず `defaults` にも存在しない場合は例外を送出する.
///
/// # 使用例
///
/// ```ts
/// const env = extractEnv(["DISCORD_TOKEN", "MAIN_CHANNEL_ID"]);
/// ```
function extractEnv<K extends string>(
keys: readonly K[],
{ defaults, emptyStrAsUnspecified = true }: {
defaults?: Readonly<Partial<Record<K, string>>>;
emptyStrAsUnspecified?: boolean;
},
): Record<K, string> {
const env: Partial<Record<K, string>> = {};
// `keys` は抽出したい環境変数名の配列で, `K` はその配列が取りうるキーのリテラル型全ての直和型が得られる.
// 例えば, `keys` が `["DISCORD_TOKEN", "MAIN_CHANNEL_ID"]` なら
// `K` は `"DISCORD_TOKEN" | "MAIN_CHANNEL_ID"` である.
// この直和型を `Record` のキーにすればいい感じの戻り値型になる.
// (`Record` についてはこちらを参照: https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeys-type)
// だから, 戻り値型は `Record<K, string>` になる.
for (const key of keys) {
// `keys` から一個ずつ取り出して
if (process.env[key] !== undefined && (!emptyStrAsUnspecified || process.env[key] !== "")) {
// 存在したらそれに設定
env[key] = process.env[key];
} else if (defaults && defaults[key] !== undefined) {
// `defaults` にフォールバック
env[key] = defaults[key];
} else {
// 存在しなければ例外を送出
throw new Error(`env is not set: ${key}`);
}
}
// すでに問題ないことを確認したので `as` で変換
return env as Record<K, string>;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment