type Writable = { -readonly [P in keyof T]: T[P]; }; interface ReadonlyConfig { readonly apiUrl: string; readonly timeout: number; readonly debugMode: boolean; } // Example Usage: type MutableConfig = Writable; const appConfig: ReadonlyConfig = { apiUrl: 'https://api.example.com', timeout: 5000, debugMode: false }; // appConfig.apiUrl = 'new_url'; // Error: Cannot assign to 'apiUrl' because it is a read-only property. // To modify, you can create a mutable copy or cast for specific operations const editableConfig: MutableConfig = { ...appConfig }; editableConfig.apiUrl = 'https://dev.api.example.com'; // OK editableConfig.timeout = 10000; // OK editableConfig.debugMode = true; // OK function processConfig(config: Writable) { // Inside this function, config properties are writable config.debugMode = true; console.log(config.debugMode); } // processConfig(appConfig); // Error because appConfig is ReadonlyConfig, and processConfig expects Writable // You'd typically pass a mutable version: processConfig({ ...appConfig }); interface NestedReadonly { readonly id: string; readonly details: { readonly name: string }; } type MutableNested = Writable; const data: NestedReadonly = { id: '1', details: { name: 'Test' }}; const mutableData: MutableNested = { ...data }; mutableData.id = '2'; // OK // mutableData.details.name = 'New Name'; // Error: 'name' is still readonly (Writable only affects top level)