Skip to main content

prefer-type-fest-partial-deep

Require TypeFest PartialDeep over DeepPartial aliases.

Targeted pattern scopeโ€‹

This rule reports DeepPartial<T> aliases and prefers PartialDeep<T> for recursive optional patch types.

What this rule reportsโ€‹

  • Type references named DeepPartial.

Detection boundariesโ€‹

  • โœ… Reports direct DeepPartial<T> type references.
  • โŒ Does not auto-fix where project-local aliases have non-TypeFest semantics.

Why this rule existsโ€‹

PartialDeep<T> is the canonical TypeFest utility for recursive optionality.

Using a single name for deep patch semantics makes update/persistence DTOs easier to audit.

โŒ Incorrectโ€‹

type Patch = DeepPartial<AppConfig>;

โœ… Correctโ€‹

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

type Patch = PartialDeep<AppConfig>;

Behavior and migration notesโ€‹

  • PartialDeep<T> recursively marks nested properties optional.
  • Validate parity if your legacy alias excluded arrays, maps, or sets.
  • Prefer narrowing the patch surface with Pick/Except before applying deep optionality.

ESLint flat config exampleโ€‹

import typefest from "eslint-plugin-typefest";

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

When not to use itโ€‹

Disable this rule if your codebase intentionally standardizes DeepPartial naming instead of TypeFest.

Package documentationโ€‹

TypeFest package documentation:

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

/**
* Create a type from another type with all keys and nested keys set to
* optional.
*
* Use-cases:
*
* - Merging a default settings/config object with another object, the second
* object would be a deep partial of the default object.
* - Mocking and testing complex entities, where populating an entire object with
* its keys would be redundant in terms of the mock or test.
*
* @category Object
* @category Array
* @category Set
* @category Map
*
* @example
* ```
* import type {PartialDeep} from 'type-fest';
*
* let settings = {
* textEditor: {
* fontSize: 14,
* fontColor: '#000000',
* fontWeight: 400,
* },
* autocomplete: false,
* autosave: true,
* };
*
* const applySavedSettings = (savedSettings: PartialDeep<typeof settings>) => (
* {...settings, ...savedSettings, textEditor: {...settings.textEditor, ...savedSettings.textEditor}}
* );
*
* settings = applySavedSettings({textEditor: {fontWeight: 500}});
* ```
*
* By default, this does not affect elements in array and tuple types. You can change this by passing `{recurseIntoArrays: true}` as the second type argument:
*
* ```
* import type {PartialDeep} from 'type-fest';
*
* type Shape = {
* dimensions: [number, number];
* };
*
* const partialShape: PartialDeep<Shape, {recurseIntoArrays: true}> = {
* dimensions: [], // OK
* };
*
* partialShape.dimensions = [15]; // OK
* ```
*
* @see {@link PartialDeepOptions}
*/

Rule catalog ID: R052

Further readingโ€‹

Adoption resourcesโ€‹