TYPESCRIPT

Deep Partial Utility

Recursive Partial type for nested objects

TypeScriptUtility TypesAdvanced Types

Code

// Basic DeepPartial type
type DeepPartial<T> = T extends object
  ? {
      [P in keyof T]?: DeepPartial<T[P]>;
    }
  : T;

// With arrays and functions support
type DeepPartialEnhanced<T> = T extends Function
  ? T
  : T extends Array<infer U>
  ? Array<DeepPartialEnhanced<U>>
  : T extends object
  ? {
      [P in keyof T]?: DeepPartialEnhanced<T[P]>;
    }
  : Partial<T>;

// Deep Required counterpart
type DeepRequired<T> = T extends object
  ? {
      [P in keyof T]-?: DeepRequired<T[P]>;
    }
  : NonNullable<T>;

// Deep Readonly
type DeepReadonly<T> = T extends Function
  ? T
  : T extends object
  ? {
      readonly [P in keyof T]: DeepReadonly<T[P]>;
    }
  : Readonly<T>;

// Merge utility type
type Merge<F, S> = {
  [K in keyof F | keyof S]: K extends keyof S
    ? S[K]
    : K extends keyof F
    ? F[K]
    : never;
};

// Usage examples
interface UserProfile {
  id: number;
  details: {
    name: string;
    address: {
      street: string;
      city: string;
      country: string;
    };
    preferences: {
      theme: 'light' | 'dark';
      notifications: boolean;
    };
  };
  tags: string[];
}

// Deep partial allows nested optional properties
const updateData: DeepPartial<UserProfile> = {
  details: {
    address: {
      city: 'New York'
    }
  }
};

// Deep required makes everything required
const completeData: DeepRequired<UserProfile> = {
  id: 1,
  details: {
    name: 'John',
    address: {
      street: '123 Main St',
      city: 'NYC',
      country: 'USA'
    },
    preferences: {
      theme: 'dark',
      notifications: true
    }
  },
  tags: ['admin', 'user']
};

// Utility function for deep merge
function deepMerge<T extends object, U extends object>(
  target: T,
  source: U
): Merge<T, U> {
  const result: any = { ...target };
  
  __TOKEN_49__ (const key in source) {
    __TOKEN_52__ (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
      result[key] = deepMerge(result[key] || {}, source[key]);
    } else {
      result[key] = source[key];
    }
  }
  
  return result;
}

// Example usage
const baseConfig = {
  api: { baseUrl: 'https://api.example.com', timeout: 5000 },
  features: { analytics: true, notifications: false }
};

const override = {
  api: { timeout: 10000 },
  features: { notifications: true }
};

const merged = deepMerge(baseConfig, override);