type DeepReadonly = T extends ((...args: any[]) => any) ? T : // Preserve functions as is T extends object ? { readonly [P in keyof T]: DeepReadonly } : T; // Example Usage: interface Address { street: string; city: string; } interface UserProfile { name: string; age: number; address: Address; hobbies: string[]; options: { notifications: boolean; theme: 'dark' | 'light'; }; logActivity: (message: string) => void; } type ImmutableUserProfile = DeepReadonly; const userProfile: ImmutableUserProfile = { name: 'John Doe', age: 30, address: { street: '123 Main St', city: 'Anytown', }, hobbies: ['reading', 'coding'], options: { notifications: true, theme: 'dark', }, logActivity: (msg: string) => console.log(msg), }; // userProfile.name = 'Jane Doe'; // Error: Cannot assign to 'name' because it is a read-only property. // userProfile.address.city = 'Otherville'; // Error: Cannot assign to 'city' because it is a read-only property. // userProfile.hobbies.push('gaming'); // Error: Property 'push' does not exist on type 'readonly string[]'. // Functions are preserved and can still be called: userProfile.logActivity('User viewed profile'); // No error