prefer-type-fest-require-one-or-none
Require TypeFest RequireOneOrNone<T, Keys> over imported aliases like AtMostOne.
Targeted pattern scopeβ
This rule reports imported AtMostOne aliases and prefers RequireOneOrNone<T, Keys> for zero-or-one selector constraints.
Use this utility when a payload may omit all optional selectors, but must not provide two selectors at the same time.
What this rule reportsβ
- Type references that resolve to imported
AtMostOnealiases.
Detection boundariesβ
- β Reports imported aliases with direct named imports.
- β Does not report namespace-qualified alias usage.
- β Does not auto-fix.
Why this rule existsβ
RequireOneOrNone is the canonical TypeFest utility for expressing βzero or exactly oneβ optional key constraints. Canonical naming keeps type utility usage predictable in public codebases.
This pattern appears in query/filter payloads where no selector is valid but multiple selectors conflict.
β Incorrectβ
import type { AtMostOne } from "type-aliases";
type OptionalAuth = AtMostOne<{
token?: string;
apiKey?: string;
}>;
β Correctβ
import type { RequireOneOrNone } from "type-fest";
type OptionalAuth = RequireOneOrNone<{
token?: string;
apiKey?: string;
}>;
Behavior and migration notesβ
RequireOneOrNone<T, Keys>models selectors where zero is valid but more than one is invalid.- This rule targets alias names with equivalent semantics (
AtMostOne). - Keep the key subset focused on mutually exclusive selectors to maintain readable contract intent.
Additional examplesβ
β Incorrect β Additional exampleβ
import type { AtMostOne } from "custom-type-utils";
type MonitorLookup = AtMostOne<
{
monitorId?: string;
slug?: string;
},
"monitorId" | "slug"
>;
β Correct β Additional exampleβ
import type { RequireOneOrNone } from "type-fest";
type MonitorLookup = RequireOneOrNone<
{
monitorId?: string;
slug?: string;
},
"monitorId" | "slug"
>;
β Correct β Repository-wide usageβ
type SessionIdentity = RequireOneOrNone<
{ userId?: string; guestId?: string },
"userId" | "guestId"
>;
ESLint flat config exampleβ
import typefest from "eslint-plugin-typefest";
export default [
{
plugins: { typefest },
rules: {
"typefest/prefer-type-fest-require-one-or-none": "error",
},
},
];
When not to use itβ
Disable this rule if existing alias names are part of a published API contract.
Package documentationβ
TypeFest package documentation:
Source file: source/require-one-or-none.d.ts
/**
Create a type that requires exactly one of the given keys and disallows more, or none of the given keys. The remaining keys are kept as is.
@example
```
import type {RequireOneOrNone} from 'type-fest';
type Responder = RequireOneOrNone<{
text: () => string;
json: () => string;
secure: boolean;
}, 'text' | 'json'>;
const responder1: Responder = {
secure: true,
};
const responder2: Responder = {
text: () => '{"message": "hi"}',
secure: true,
};
const responder3: Responder = {
json: () => '{"message": "ok"}',
secure: true,
};
```
@category Object
*/
Rule catalog ID: R059