Skip to main content

prefer-ts-extras-as-writable

Prefer asWritable from ts-extras over Writable<...> type assertions.

Targeted pattern scopeโ€‹

This rule focuses on mutation-intent type assertions that map directly to asWritable(value).

Matched patternsโ€‹

  • as assertions where the asserted type is Writable<...> imported from type-fest.
  • Namespace-qualified assertions such as TypeFest.Writable<...> when TypeFest comes from type-fest.

Detection boundariesโ€‹

  • โœ… Reports Writable-based type assertions that are direct helper replacements.
  • โŒ Does not report unrelated as assertions with non-Writable target types.

These boundaries keep matching deterministic and avoid broad semantic overreach during migration.

What this rule reportsโ€‹

Writable<...>-based type assertions that can be replaced with asWritable(value).

Why this rule existsโ€‹

asWritable(value) communicates intent directly and keeps mutation-intent casts aligned with the ts-extras helper API.

โŒ Incorrectโ€‹

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

const writableUser = readonlyUser as Writable<User>;

โœ… Correctโ€‹

import { asWritable } from "ts-extras";

const writableUser = asWritable(readonlyUser);

Behavior and migration notesโ€‹

  • asWritable(value) preserves runtime behavior while expressing mutability intent through one helper.
  • Direct as Writable<T> / as TypeFest.Writable<T> assertions are reported.
  • This rule does not rewrite unrelated type assertions.

Additional examplesโ€‹

โŒ Incorrect โ€” Additional exampleโ€‹

const mutable = config as Writable<typeof config>;

โœ… Correct โ€” Additional exampleโ€‹

const mutable = asWritable(config);

โœ… Correct โ€” Repository-wide usageโ€‹

const draft = asWritable(readonlyDraft);

ESLint flat config exampleโ€‹

import typefest from "eslint-plugin-typefest";

export default [
{
plugins: { typefest },
rules: {
"typefest/prefer-ts-extras-as-writable": "error",
},
},
];

When not to use itโ€‹

Disable this rule if mutation boundaries are enforced through explicit type assertions by policy.

Package documentationโ€‹

ts-extras package documentation:

Source file: source/as-writable.ts

/**
Cast the given value to be [`Writable`](https://github.com/sindresorhus/type-fest/blob/main/source/writable.d.ts).

This is useful because of a [TypeScript limitation](https://github.com/microsoft/TypeScript/issues/45618#issuecomment-908072756).

@example
```
import {asWritable} from 'ts-extras';

const writableContext = asWritable((await import('x')).context);
```

@category General
*/

Rule catalog ID: R010

Further readingโ€‹

Adoption resourcesโ€‹