#17973Medium

DeepMutable

Implement a generic DeepMutable<T> which make every parameter of an object - and its sub-objects recursively - mutable. Learn recursive type definitions, readonly modifiers in this medium-level challenge on TypeScriptPro.

In this medium-level challenge, you'll implement DeepMutable<T> which recursively removes all readonly modifiers from every property of an object and its nested sub-objects, including arrays.

Challenge Instructions: DeepMutable

Medium

Implement a generic DeepMutable<T> which make every parameter of an object - and its sub-objects recursively - mutable.

For example

type X = {
readonly a: () => 1
readonly b: string
readonly c: {
readonly d: boolean
readonly e: {
readonly g: {
readonly h: {
readonly i: true
readonly j: "s"
}
readonly k: "hello"
}
}
}
}
 
type Expected = {
a: () => 1
b: string
c: {
d: boolean
e: {
g: {
h: {
i: true
j: "s"
}
k: "hello"
}
}
}
}
 
type Todo = DeepMutable<X> // should be same as `Expected`

You can assume that we are only dealing with Objects in this challenge. Arrays, Functions, Classes and so on do not need to be taken into consideration. However, you can still challenge yourself by covering as many different cases as possible.

Change the following code to make the test cases pass (no type check errors).

ChallengeSolution
interface Test1 {
  readonly title: string
  readonly description: string
  readonly completed: boolean
  readonly meta: {
    readonly author: string
  }
}
type Test2 = {
  readonly a: () => 1
  readonly b: string
  readonly c: {
    readonly d: boolean
    readonly e: {
      readonly g: {
        readonly h: {
          readonly i: true
          readonly j: 's'
        }
        readonly k: 'hello'
      }
      readonly l: readonly [
        'hi',
        {
          readonly m: readonly ['hey']
        },
      ]
    }
  }
}
interface DeepMutableTest1 {
  title: string
  description: str

Pro Challenge

Unlock 102+ medium, hard, and extreme challenges to master advanced TypeScript.

One-time payment. Lifetime access.

Detailed Explanation

type DeepMutable<T extends Record<string, any>> = {
  -readonly [K in keyof T]: T[K] extends (...args: any[]) => any
    ? T[K]
    : T[K] extends object
      ? DeepMutable<T[K]>
      : T[K]
}

How it works:

This challenge helps you understand the -readonly mapped type modifier and recursive type traversal, and how to apply these concepts in real-world scenarios.

This challenge is originally from here.

Share this challenge

Learn the Concepts