Skip to main content

prefer-type-fest-schema

Require TypeFest Schema<ObjectType, ValueType> over imported aliases like RecordDeep.

Targeted pattern scopeโ€‹

This rule keeps deep object-shape transforms on the canonical type-fest utility: Schema<ObjectType, ValueType>.

It is designed for consistency, not aggressive rewriting. Replacing third-party aliases such as RecordDeep with Schema is usually straightforward, but you should still validate semantics if your old utility had custom behavior.

What this rule reportsโ€‹

  • Imported RecordDeep aliases used as identifier type references.

Detection boundariesโ€‹

  • โœ… Reports import type { RecordDeep } ... + RecordDeep<...> usage.
  • โŒ Does not report locally renamed imports (RecordDeep as AliasRecordDeep).
  • โŒ Does not report namespace-qualified usages such as TypeUtils.RecordDeep<...>.
  • โŒ Does not auto-fix.

Why this rule existsโ€‹

Schema is the canonical TypeFest utility for deep value-shape transformation across object types. Standardized naming helps readers recognize intent immediately.

type-fest describes itself as "A collection of essential TypeScript types". Using canonical names means engineers can jump directly between your code and upstream docs without translation.

โŒ Incorrectโ€‹

import type { RecordDeep } from "type-aliases";

type Flags = RecordDeep<Config, boolean>;

โœ… Correctโ€‹

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

type Flags = Schema<Config, boolean>;

Behavior and migration notesโ€‹

  • Schema<ObjectType, ValueType> recursively maps leaf value types while preserving object shape.
  • This rule targets imported alias names with overlapping semantics (RecordDeep).
  • Validate behavior if your previous alias implemented custom deep-mapping edge cases beyond Schema.

Additional examplesโ€‹

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

import type { RecordDeep } from "custom-type-utils";

type AuditMask = RecordDeep<UserProfile, "REDACTED">;

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

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

type AuditMask = Schema<UserProfile, "REDACTED">;

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

type FeatureFlags = Schema<EnvironmentConfig, boolean>;

ESLint flat config exampleโ€‹

import typefest from "eslint-plugin-typefest";

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

When not to use itโ€‹

Disable this rule if existing deep-shape aliases encode custom semantics that differ from Schema.

Package documentationโ€‹

TypeFest package documentation:

Source file: source/schema.d.ts

/**
* Create a deep version of another object type where property values are
* recursively replaced into a given value type.
*
* Use-cases:
*
* - Form validation: Define how each field should be validated.
* - Form settings: Define configuration for input fields.
* - Parsing: Define types that specify special behavior for specific fields.
*
* @category Object
*
* @example
* ```
* import type {Schema} from 'type-fest';
*
* type User = {
* id: string;
* name: {
* firstname: string;
* lastname: string;
* };
* created: Date;
* active: boolean;
* passwordHash: string;
* location: [latitude: number, longitude: number];
* };
*
* type UserMask = Schema<User, 'mask' | 'hide' | 'show'>;
*
* const userMaskSettings: UserMask = {
* id: 'show',
* name: {
* firstname: 'show',
* lastname: 'mask',
* },
* created: 'show',
* active: 'show',
* passwordHash: 'hide',
* location: ['hide', 'hide'],
* };
* ```;
*
* @see {@link SchemaOptions}
*/

Rule catalog ID: R061

Further readingโ€‹

Adoption resourcesโ€‹