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.

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

@category Object
@category Array
@category Set
@category Map
*/

Rule catalog ID: R052

Further readingโ€‹

Adoption resourcesโ€‹