Управление конфигурацией TypeScript-приложений: полное руководство

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Конфигурация приложений TypeScript: от простого к сложному

Любое современное приложение требует гибкой и безопасной настройки. Будь то API-ключи, параметры подключения к базе данных, порты сервера или флаги фич — конфигурация должна быть отделена от кода, легко читаться и валидироваться на этапе запуска. В мире TypeScript эта задача имеет свои особенности: типизация конфигурации даёт автодополнение и предотвращает ошибки времени выполнения. В этой статье мы разберём лучшие практики, популярные библиотеки и инструменты для управления конфигурацией TypeScript-приложений.

Почему не стоит использовать process.env напрямую?

На первый взгляд, чтение переменных окружения через process.env кажется простым решением. Однако такой подход имеет существенные недостатки:

  • Отсутствие типизации: все значения — строки, даже если по логике это число или булево значение.
  • Риск опечаток: легко написать process.env.DB_HOTS вместо DB_HOST и получить undefined.
  • Отсутствие валидации: если обязательная переменная не задана, приложение упадёт в самый неожиданный момент, а не при старте.

Грамотная конфигурация решает все эти проблемы.

Библиотека dotenv и её TypeScript-обёртки

Стандартом де-факто для загрузки .env файлов является библиотека dotenv. Для TypeScript удобно использовать dotenv-flow или dotenv-expand, поддерживающие несколько окружений (development, staging, production).

// Установка
// npm install dotenv dotenv-expand

// config/env.ts
import dotenv from 'dotenv';
import dotenvExpand from 'dotenv-expand';

const myEnv = dotenv.config({ path: `.env.${process.env.NODE_ENV || 'development'}` });
dotenvExpand.expand(myEnv);

После вызова этой функции все переменные из .env файла будут доступны через process.env, но мы всё ещё не имеем типов.

Валидация схемы с помощью Zod

Zod — мощная библиотека для декларативной валидации схем с первоклассной поддержкой TypeScript. Она идеально подходит для конфигурации:

// config/schema.ts
import { z } from 'zod';

const envSchema = z.object({
  NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
  PORT: z.coerce.number().positive().default(3000),
  DATABASE_URL: z.string().url(),
  JWT_SECRET: z.string().min(32),
  REDIS_HOST: z.string().default('localhost'),
  REDIS_PORT: z.coerce.number().default(6379),
  FEATURE_NEW_UI: z
    .string()
    .transform((val) => val === 'true')
    .default('false'),
});

export type EnvConfig = z.infer<typeof envSchema>;

Теперь мы можем безопасно распарсить и провалидировать окружение на старте:

// config/index.ts
import { envSchema, EnvConfig } from './schema';

let config: EnvConfig;

export function loadConfig(): EnvConfig {
  if (config) return config; // кеширование

  const result = envSchema.safeParse(process.env);
  if (!result.success) {
    console.error('❌ Invalid environment variables:', result.error.flatten().fieldErrors);
    process.exit(1);
  }
  config = result.data;
  return config;
}

export function getConfig(): EnvConfig {
  if (!config) throw new Error('Config not loaded. Call loadConfig() first.');
  return config;
}

Библиотека Conf для управления конфигурацией приложения

Если ваше приложение требует не только чтения, но и записи конфигурации (например, настройки пользователя, кэш), обратите внимание на conf от Sindre Sorhus. Она хранит данные в JSON-файле и полностью типизирована.

// Установка
// npm install conf

import Conf from 'conf';

interface AppConfig {
  lastOpenedProject: string;
  theme: 'light' | 'dark';
  windowBounds: { width: number; height: number };
}

const store = new Conf<AppConfig>({
  projectName: 'my-app',
  defaults: {
    theme: 'light',
    windowBounds: { width: 800, height: 600 },
  },
});

store.set('theme', 'dark');
console.log(store.get('theme')); // 'dark'

Conf автоматически выбирает путь для хранения в зависимости от ОС (Linux: ~/.config/my-app/config.json, macOS: ~/Library/Application Support/my-app/config.json).

Инструмент ConfigCat — фиче-флаги и удалённая конфигурация

Для крупных проектов, где конфигурация должна меняться без деплоя, идеально подходит

Рекомендаций