Type-Fest DeepPartial Merge Utility

Model patch updates with type-fest DeepPartial, merging partial trees into complete config objects while preserving nested key typing.

TypescriptData Integrity

Code

snippet
import type { DeepPartial } from 'type-fest';

interface ServerConfig {
  http: { port: number; bodyLimitMb: number };
  db: { url: string; poolSize: number };
  features: { auditLog: boolean; darkMode: boolean };
}

function mergeConfig<T extends object>(base: T, patch: DeepPartial<T>): T {
  const result: Record<string, unknown> = { ...base };

  for (const [key, patchValue] of Object.entries(patch)) {
    const baseValue = (base as Record<string, unknown>)[key];
    const bothObjects =
      patchValue && typeof patchValue === 'object' && !Array.isArray(patchValue)
      && baseValue && typeof baseValue === 'object' && !Array.isArray(baseValue);

    result[key] = bothObjects
      ? mergeConfig(baseValue, patchValue)
      : patchValue;
  }
  return result as T;
}

const defaults: ServerConfig = {
  http: { port: 3000, bodyLimitMb: 1 },
  db: { url: 'postgres://localhost/app', poolSize: 10 },
  features: { auditLog: true, darkMode: false },
};

const merged = mergeConfig(defaults, { http: { port: 8080 }, features: { darkMode: true } });
console.log(merged.http.port, merged.db.poolSize, merged.features.darkMode);