Mutable
Mutable
Problem
Implement the generic Mutable<T> which makes all properties in T mutable (removes readonly).
interface Todo {
readonly title: string
readonly description: string
readonly completed: boolean
}
type MutableTodo = Mutable<Todo>
// {
// title: string
// description: string
// completed: boolean
// }Solution
Approach 1: Mapped Type with -readonly Modifier
The most direct solution uses TypeScript's -readonly modifier in a mapped type to strip the readonly qualifier from every property:
type Mutable<T extends object> = {
-readonly [K in keyof T]: T[K]
}How it works:
[K in keyof T]iterates over all keys ofT.-readonlyremoves thereadonlymodifier from each property.T[K]preserves the original value type unchanged.
This is the idiomatic, one-liner solution.
Approach 2: Using as Remapping (explicit)
You can make the remapping more explicit with as:
type Mutable<T extends object> = {
-readonly [K in keyof T as K]: T[K]
}This is functionally identical to Approach 1 but shows the key remapping step explicitly. Useful when you also want to filter or rename keys.
Approach 3: Utility Type Composition
If you already have built-in Required in scope, you might be tempted to combine it, but Required only removes ? (optionality), not readonly. There's no built-in Mutable in TypeScript's standard library — that's exactly why this challenge exists!
For reference, the mirror type Readonly<T> from the standard library adds readonly:
// Standard library Readonly (adds readonly):
type Readonly<T> = {
readonly [K in keyof T]: T[K]
}
// Our Mutable (removes readonly):
type Mutable<T extends object> = {
-readonly [K in keyof T]: T[K]
}Approach 4: Deep Mutable
The challenge only asks for shallow mutability, but in practice you often need recursion:
type DeepMutable<T> = T extends object
? { -readonly [K in keyof T]: DeepMutable<T[K]> }
: TThis recursively removes readonly from nested objects as well.
Key Takeaways
- TypeScript supports
+and-prefixes on mapped type modifiers (readonlyand?). -readonlyremoves the readonly modifier;+readonly(or justreadonly) adds it.-?removes optionality (same asRequired<T>);+?adds it.- The standard library has no
Mutable<T>— you need to write it yourself.
| Modifier | Effect |
|---|---|
readonly or +readonly | Make property readonly |
-readonly | Remove readonly |
? or +? | Make property optional |
-? | Make property required |
