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.

@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}

@category Object
*/

Rule catalog ID: R061

Further readingโ€‹

Adoption resourcesโ€‹