Skip to main content

prefer-type-fest-writable-deep

Require TypeFest WritableDeep over DeepMutable and MutableDeep aliases.

Targeted pattern scopeโ€‹

This rule reports DeepMutable<T>/MutableDeep<T> aliases and prefers WritableDeep<T> for deep mutability transforms.

What this rule reportsโ€‹

  • Type references named DeepMutable.
  • Type references named MutableDeep.

Detection boundariesโ€‹

  • โœ… Reports direct DeepMutable<T> and MutableDeep<T> references.
  • โŒ Does not auto-fix where internal helpers intentionally diverge from WritableDeep behavior.

Why this rule existsโ€‹

WritableDeep<T> is the canonical TypeFest utility for recursively removing readonly constraints.

Standardizing on one helper name reduces confusion when mutability transitions are part of data-processing pipelines.

โŒ Incorrectโ€‹

type MutableConfigA = DeepMutable<AppConfig>;
type MutableConfigB = MutableDeep<AppConfig>;

โœ… Correctโ€‹

import type { WritableDeep } from "type-fest";

type MutableConfig = WritableDeep<AppConfig>;

Behavior and migration notesโ€‹

  • WritableDeep<T> recursively removes readonly modifiers from nested members.
  • Validate migration behavior for tuple/read-only array branches in critical types.
  • Prefer local wrapper aliases if your domain needs a narrower deep-writable contract.

ESLint flat config exampleโ€‹

import typefest from "eslint-plugin-typefest";

export default [
{
plugins: { typefest },
rules: {
"typefest/prefer-type-fest-writable-deep": "error",
},
},
];

When not to use itโ€‹

Disable this rule if your codebase intentionally standardizes deep-mutable aliases over TypeFest naming.

Package documentationโ€‹

TypeFest package documentation:

Source file: source/writable-deep.d.ts

/**
Create a deeply mutable version of an `object`/`ReadonlyMap`/`ReadonlySet`/`ReadonlyArray` type. The inverse of `ReadonlyDeep<T>`. Use `Writable<T>` if you only need one level deep.

This can be used to [store and mutate options within a class](https://github.com/sindresorhus/pageres/blob/4a5d05fca19a5fbd2f53842cbf3eb7b1b63bddd2/source/index.ts#L72), [edit `readonly` objects within tests](https://stackoverflow.com/questions/50703834), [construct a `readonly` object within a function](https://github.com/Microsoft/TypeScript/issues/24509), or to define a single model where the only thing that changes is whether or not some of the keys are writable.

@example
```
import type {WritableDeep} from 'type-fest';

type Foo = {
readonly a: number;
readonly b: readonly string[]; // To show that mutability is deeply affected.
readonly c: boolean;
};

const writableDeepFoo: WritableDeep<Foo> = {a: 1, b: ['2'], c: true};
writableDeepFoo.a = 3;
writableDeepFoo.b[0] = 'new value';
writableDeepFoo.b = ['something'];
```

Note that types containing overloaded functions are not made deeply writable due to a [TypeScript limitation](https://github.com/microsoft/TypeScript/issues/29732).

@see {@link Writable}
@category Object
@category Array
@category Set
@category Map
*/

Rule catalog ID: R076

Further readingโ€‹

Adoption resourcesโ€‹