TL;DR: The Fast Fixes
Stuck on a deadline? Use one of these three methods to get your code running immediately:
- Edit the source: Find the interface or type and delete the
readonlykeyword. - Force the change: Use a type assertion to bypass the check:
(myObject as any).property = 'new value';. - Drop the const: If you defined your object with
as const, remove that suffix to make the object mutable again.
Why TypeScript Blocks Your Edit
You'll run into this error when the compiler spots an attempt to change a value that was explicitly marked as immutable. TypeScript does this to prevent bugs caused by unexpected state changes. Usually, the culprit is one of these three scenarios:
- The property in the interface or type has a
readonlyprefix. - The object was declared with a Const Assertion (
as const), making every field immutable. - You are trying to update a class property that was marked
readonlyoutside of the constructor.
interface User {
readonly id: number;
name: string;
}
const user: User = { id: 101, name: 'Alice' };
// โ Error: Cannot assign to 'id' because it is a read-only property.
user.id = 202;
4 Ways to Resolve the Error
1. Modify the Interface Definition
The simplest approach is to allow the property to change. If your logic requires updating a value, like a retryCount or a lastLogin timestamp, the readonly flag shouldn't be there in the first place.
// Before: Immutable
interface AppConfig {
readonly port: number;
}
// After: Mutable
interface AppConfig {
port: number;
}
2. Use a Type Assertion (The Escape Hatch)
You might encounter this when using third-party libraries where you can't edit the source code. In these cases, you can tell TypeScript to "trust you" by casting the object. This is common in unit tests when you need to mock specific data states.
interface Profile {
readonly email: string;
}
const userProfile: Profile = { email: 'test@example.com' };
// Option A: Cast to any
(userProfile as any).email = 'new@example.com';
// Option B: Create a Writable utility type
type Writable<T> = { -readonly [P in keyof T]: T[P] };
(userProfile as Writable<Profile>).email = 'admin@internal.com';
3. Remove "as const" Assertions
Using as const is a handy way to create literal types, but it locks down every nested property. If you need to change a theme setting from 'dark' to 'light', don't use a const assertion for the whole object.
// This object is 100% locked
const UI_SETTINGS = {
theme: 'dark',
sidebarWidth: 250
} as const;
// UI_SETTINGS.theme = 'light'; // โ This will fail
// Fix: Use a standard object or a specific type
const UI_SETTINGS = {
theme: 'dark',
sidebarWidth: 250
};
4. Convert Readonly Arrays
Methods like push(), pop(), or splice() will trigger this error if the array is defined as readonly string[]. Since these methods mutate the original array, TypeScript blocks them. To fix this, create a mutable copy using the spread operator.
const roles: readonly string[] = ['admin', 'editor'];
// roles.push('viewer'); // โ Error
// Fix: Spread into a new array
const activeRoles = [...roles];
activeRoles.push('viewer'); // โ
Works perfectly
How to Double-Check Your Work
Once you apply a fix, verify it with these three steps:
- Look for the red line: VS Code should immediately remove the red squiggly underline.
- Run a build: Fire up your terminal and run
npx tsc. If it finishes without errors, your fix is type-safe. - Verify the JS: If you used
as any, remember that TypeScript won't help you at runtime. Check your logs or browser console to ensure the value actually updated.
Pro Tip: Stay Immutable When Possible
Don't just delete readonly to make an error go away. Immutability makes your code easier to debug. If you're working in React or Redux, instead of forcing a change on a read-only property, always return a new object: const updated = { ...oldObject, status: 'active' };. This keeps your data flow predictable and avoids side effects.

