Review a configuration precedence loader

src/config-loader.tsTypeScript
@@ -0,0 +1,42 @@
1+export interface RawConfig {
2+ port?: string;
3+ apiBaseUrl?: string;
4+ debug?: boolean;
5+}
6+
7+export interface ServiceConfig {
8+ port: number;
9+ apiBaseUrl: string;
10+ debug: boolean;
11+}
12+
13+const defaults: RawConfig = {
14+ port: "8080",
15+ apiBaseUrl: "https://api.example.test",
16+ debug: false,
17+};
18+
19+function compact(source: RawConfig): RawConfig {
20+ return Object.fromEntries(
21+ Object.entries(source).filter(([, value]) => Boolean(value)),
22+ ) as RawConfig;
23+}
24+
25+export function loadConfig(
26+ file: RawConfig,
27+ environment: RawConfig,
28+ cli: RawConfig,
29+): ServiceConfig {
30+ const merged = Object.assign(
31+ defaults,
32+ compact(cli),
33+ compact(environment),
34+ compact(file),
35+ );
36+
37+ return {
38+ port: Number(merged.port),
39+ apiBaseUrl: merged.apiBaseUrl ?? "",
40+ debug: merged.debug ?? false,
41+ };
42+}