Skip to content

DeepWritable

Recursively removes readonly from all properties of T, including nested objects, array elements, and tuple positions.

Available since v2.0.2

import type { DeepWritable } from '@helpers4/type';
// or, from the all-in-one package (same code, one install):
import type { DeepWritable } from 'helpers4/type';
type DeepWritable<T> =
  T extends readonly (infer U)[]
    ? number extends T['length'] ? DeepWritable<U>[] : { -readonly [K in keyof T]: DeepWritable<T[K]> }
    : T extends (...args: never[]) => unknown
      ? T
      : T extends Date | Map<unknown, unknown> | Set<unknown> | Promise<unknown> | RegExp
        ? T
        : T extends object
          ? { -readonly [K in keyof T]: DeepWritable<T[K]> }
          : T
type Config = { readonly server: { readonly host: string }; readonly tags: readonly string[] };
type MutableConfig = DeepWritable<Config>;
// => { server: { host: string }; tags: string[] }
type Point = readonly [x: number, y: number];
type MutablePoint = DeepWritable<Point>;
// => [x: number, y: number]

Note: `Date`, `Map`, `Set`, `Promise`, and `RegExp` are treated as opaque and passed
through unchanged. In particular, `DeepWritable<Map<K, V>>` does **not** strip `readonly`
from the value type `V` — use a manual mapped type if you need that.

View source on GitHub