Skip to main content

prefer-type-fest-readonly-keys-of

Require TypeFest ReadonlyKeysOf<T> over expanded readonly-key extraction helpers.

Targeted pattern scopeโ€‹

This rule reports the exact TypeFest mapped-key composition that derives readonly keys from IsReadonlyKeyOf<T, K>.

It supports direct, aliased, and namespace-qualified TypeFest imports for IsReadonlyKeyOf.

What this rule reportsโ€‹

This rule reports expanded readonly-key extraction helpers that can be replaced by ReadonlyKeysOf<T>.

Why this rule existsโ€‹

ReadonlyKeysOf<T> is the canonical TypeFest utility for extracting readonly keys. Using it directly makes modifier introspection clearer and avoids repeating TypeFest internals.

โŒ Incorrectโ€‹

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

type Result<Type extends object> = Type extends unknown
? (keyof {
[Key in keyof Type as IsReadonlyKeyOf<Type, Key> extends false
? never
: Key]: never;
}) &
keyof Type
: never;

โœ… Correctโ€‹

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

type Result<Type extends object> = ReadonlyKeysOf<Type>;

Behavior and migration notesโ€‹

  • The IsReadonlyKeyOf reference must resolve to a type-fest import.
  • The rule only reports the exact distributive mapped-key shape used by TypeFest.
  • Custom mapped-key filters and non-distributive helpers are ignored.
  • Autofix is skipped when ReadonlyKeysOf is shadowed in the local scope.

Additional examplesโ€‹

โŒ Incorrect โ€” Namespace importโ€‹

import type * as TypeFest from "type-fest";

type Result<Type extends object> = Type extends unknown
? (keyof {
[Key in keyof Type as TypeFest.IsReadonlyKeyOf<
Type,
Key
> extends false
? never
: Key]: never;
}) &
keyof Type
: never;

โœ… Correct โ€” Namespace importโ€‹

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

type Result<Type extends object> = ReadonlyKeysOf<Type>;

โœ… Correct โ€” Custom mappingโ€‹

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

type Result<Type extends object> = keyof {
[Key in keyof Type as IsReadonlyKeyOf<Type, Key> extends false
? never
: Key]: never;
};

ESLint flat config exampleโ€‹

import typefest from "eslint-plugin-typefest";

export default [
{
plugins: { typefest },
rules: {
"typefest/prefer-type-fest-readonly-keys-of": "error",
},
},
];

When not to use itโ€‹

Disable this rule if a public helper must intentionally expose the expanded mapped-type implementation.

Package documentationโ€‹

TypeFest package documentation:

Source file: source/readonly-keys-of.d.ts

Rule catalog ID: R123

Further readingโ€‹

Adoption resourcesโ€‹