Deep Partial Mapped Type

Recursively make every property optional with a mapped type, the right shape for patch updates and nested test fixtures.

TypescriptData Integrity

Code

snippet
export type DeepPartial<T> = T extends (infer U)[]
  ? DeepPartial<U>[]
  : T extends object
    ? { [K in keyof T]?: DeepPartial<T[K]> }
    : T;

export interface Account {
  id: string;
  profile: {
    name: string;
    address: { city: string; zip: string };
  };
}

export function applyPatch(base: Account, patch: DeepPartial<Account>): Account {
  return {
    ...base,
    ...patch,
    profile: { ...base.profile, ...(patch.profile ?? {}) },
  };
}