Код Middle Утилитарные типы спрашивают часто обновлено

Типизированный конфиг из process.env

Условие

Напиши loadConfig(env: Record<string, string | undefined>), возвращающую { ok: true; config: Config } | { ok: false; errors: string[] }, где Config = { port: number; databaseUrl: string; logLevel: 'debug' | 'info' | 'warn' | 'error'; features: string[] }.

Правила: PORT целое 1-65535, по умолчанию 3000; DATABASE_URL обязателен; LOG_LEVEL из списка, по умолчанию info; FEATURES список через запятую (пробелы обрезать, пустые выкинуть), по умолчанию пустой. Ошибки копятся все сразу, по порядку полей, в виде PORT: invalid, DATABASE_URL: required, LOG_LEVEL: invalid.

Допустимые уровни логов держи в const LEVELS = [...] as const и выведи тип из него.

Примеры

loadConfig({"DATABASE_URL":"postgres://db/app"}) // {"ok":true,"config":{"port":3000,"databaseUrl":"postgres://db/app","logLevel":"info","features":[]}}
loadConfig({"PORT":"8080","DATABASE_URL":"pg","LOG_LEVEL":"debug","FEATURES":" a, ,b "}) // {"ok":true,"config":{"port":8080,"databaseUrl":"pg","logLevel":"debug","features":["a","b"]}}
loadConfig({"PORT":"abc","LOG_LEVEL":"verbose"}) // {"ok":false,"errors":["PORT: invalid","DATABASE_URL: required","LOG_LEVEL: invalid"]}

Как подойти

Подсказки: 2
  1. (typeof LEVELS)[number] даёт объединение литералов из массива as const.
  2. includes у readonly LogLevel[] не примет string: расширь массив до readonly string[] для проверки.

Решите в тренажёре

Редактор с автотестами прямо в браузере. Можно решить спокойно, вслух или под таймером, как на собесе.