prefer-type-fest-merge
Prefer Merge from type-fest over Except<Destination, keyof Source> & Source intersections.
This rule lives only in the experimental preset and reports without autofixing.
Targeted pattern scopeโ
This rule focuses on direct merge-style intersections that already use Except from type-fest to remove overridden keys before intersecting with the overriding source type.
Except<Destination, keyof Source> & SourceSource & Except<Destination, keyof Source>
It intentionally skips builtin Omit forms and broader intersections to avoid overlapping with stable rules and to keep the report signal narrow.
What this rule reportsโ
This rule reports intersections when all of the following are true:
- one intersection member resolves to
Except - the second type argument to
Exceptis exactlykeyof Source - the sibling intersection member is exactly
Source
The rule is currently report-only. It does not autofix or suggest a replacement yet.
Why this rule existsโ
Merge<Destination, Source> states the override relationship directly.
- Readers do not need to unpack an
Except-plus-intersection recipe. - The canonical helper signals that the second type wins on overlapping keys.
- The upstream utility also simplifies the resulting object type for tooling display.
โ Incorrectโ
import type {Except} from "type-fest";
type Base = {
id: string;
name: string;
};
type Overrides = {
name: number;
readonly ok: true;
};
type Combined = Except<Base, keyof Overrides> & Overrides;
โ Correctโ
import type {Merge} from "type-fest";
type Base = {
id: string;
name: string;
};
type Overrides = {
name: number;
readonly ok: true;
};
type Combined = Merge<Base, Overrides>;
Behavior and migration notesโ
- This rule only reports the exact
Except<Destination, keyof Source> & Sourcepattern. - It ignores
Omit<Destination, keyof Source> & Sourceso it does not double-report withprefer-type-fest-except. - It ignores intersections whose sibling type does not match the
keyofoperand exactly.
Additional examplesโ
โ Incorrect โ Additional exampleโ
import type {Except as StrictExcept} from "type-fest";
type Base = {
id: string;
name: string;
};
type Overrides = {
name: number;
readonly ok: true;
};
type Combined = Overrides & StrictExcept<Base, keyof Overrides>;
โ Correct โ Additional exampleโ
import type {Merge} from "type-fest";
type Base = {
id: string;
name: string;
};
type Overrides = {
name: number;
readonly ok: true;
};
type Combined = Merge<Base, Overrides>;
ESLint flat config exampleโ
import typefest from "eslint-plugin-typefest";
export default [typefest.configs.experimental];
When not to use itโ
Disable this rule if your team prefers the explicit Except<..., keyof ...> & ... construction, or if you want to keep the override mechanism visible in source types.
Package documentationโ
TypeFest package documentation:
Source file: source/merge.d.ts
import type {Merge} from "type-fest";
type Foo = {
a: string;
b: number;
};
type Bar = {
a: number;
c: boolean;
};
type FooBar = Merge<Foo, Bar>;
//=> {a: number; b: number; c: boolean}
Rule catalog ID: R088