Skip to main content

prefer-type-fest-conditional-except

Prefer ConditionalExcept from type-fest over Except<Base, ConditionalKeys<Base, Condition>> compositions.

This rule lives only in the experimental preset and reports without autofixing.

Targeted pattern scopeโ€‹

This rule focuses on direct type-fest compositions that already use both Except and ConditionalKeys together.

  • Except<Base, ConditionalKeys<Base, Condition>>
  • the same shape when Except and ConditionalKeys are imported under local aliases from type-fest

It intentionally skips builtin Omit<Base, ConditionalKeys<Base, Condition>> shapes to avoid overlapping with the stable prefer-type-fest-except rule.

What this rule reportsโ€‹

This rule reports type-fest compositions when all of the following are true:

  • the outer type reference resolves to Except
  • the second type argument resolves to ConditionalKeys
  • the base type passed to Except matches the base type passed to ConditionalKeys

The rule is currently report-only. It does not autofix or suggest a replacement yet.

Why this rule existsโ€‹

ConditionalExcept<Base, Condition> expresses the intent of conditional omission directly.

  • Readers do not need to mentally expand two helper types to understand the result.
  • The single helper form is shorter and easier to scan in large type aliases.
  • The intent stays aligned with the upstream Type-Fest utility that already models this exact composition.

โŒ Incorrectโ€‹

import type {ConditionalKeys, Except} from "type-fest";

type Example = {
count: number;
enabled: boolean;
name: string;
};

type NonStrings = Except<Example, ConditionalKeys<Example, string>>;

โœ… Correctโ€‹

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

type Example = {
count: number;
enabled: boolean;
name: string;
};

type NonStrings = ConditionalExcept<Example, string>;

Behavior and migration notesโ€‹

  • This rule only reports the direct Except<..., ConditionalKeys<...>> composition.
  • It ignores builtin Omit forms on purpose to avoid duplicate reporting with prefer-type-fest-except.
  • It ignores compositions where the ConditionalKeys base type does not exactly match the Except base type.

Additional examplesโ€‹

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

import type {ConditionalKeys as MatchingKeys, Except as StrictExcept} from "type-fest";

type Example = {
count: number;
enabled: boolean;
name: string;
};

type NonStrings = StrictExcept<Example, MatchingKeys<Example, string>>;

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

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

type Example = {
count: number;
enabled: boolean;
name: string;
};

type NonStrings = ConditionalExcept<Example, string>;

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 explicit helper-type composition over the shorter canonical alias, or if you want Except and ConditionalKeys to stay visible for teaching purposes.

Package documentationโ€‹

TypeFest package documentation:

Source file: source/conditional-except.d.ts

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

type Example = {
a: string;
b: string | number;
c: () => void;
};

type NonStringKeysOnly = ConditionalExcept<Example, string>;
//=> {b: string | number; c: () => void}

Rule catalog ID: R087

Further readingโ€‹

Adoption resourcesโ€‹