Deep Partial Utility
Recursive Partial type for nested objects
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);