prefer-type-fest-require-at-least-one
Require TypeFest RequireAtLeastOne<T, Keys> over imported aliases like
AtLeastOne.
Targeted pattern scopeโ
This rule reports imported AtLeastOne aliases and prefers RequireAtLeastOne<T, Keys> for at-least-one field requirements.
It is especially valuable for search DTOs and patch/update payloads where empty objects should be rejected at compile time.
What this rule reportsโ
- Type references that resolve to imported
AtLeastOnealiases.
Detection boundariesโ
- โ Reports imported aliases with direct named imports.
- โ Does not report namespace-qualified aliases.
- โ Does not auto-fix.
Why this rule existsโ
RequireAtLeastOne is the canonical TypeFest utility for enforcing at least one
required key among a set of optional candidates. Standardizing on canonical
TypeFest naming keeps public type contracts easier to understand and maintain.
For user-facing APIs, this avoids accepting meaningless payloads like {}
where at least one filter field is required.
โ Incorrectโ
import type { AtLeastOne } from "type-aliases";
type Update = AtLeastOne<User>;
โ Correctโ
import type { RequireAtLeastOne } from "type-fest";
type Update = RequireAtLeastOne<User>;
Behavior and migration notesโ
RequireAtLeastOne<T, Keys>prevents empty-object payloads when at least one selector is required.- This rule targets alias names with equivalent semantics (
AtLeastOne). - Use keyed variants for large object types to constrain only the fields that participate in the requirement.
Additional examplesโ
โ Incorrect โ Additional exampleโ
import type { AtLeastOne } from "custom-type-utils";
type UserSearch = AtLeastOne<
{
email?: string;
id?: string;
username?: string;
},
"email" | "id" | "username"
>;
โ Correct โ Additional exampleโ
import type { RequireAtLeastOne } from "type-fest";
type UserSearch = RequireAtLeastOne<
{
email?: string;
id?: string;
username?: string;
},
"email" | "id" | "username"
>;
โ Correct โ Repository-wide usageโ
type ProfilePatch = RequireAtLeastOne<
{ avatarUrl?: string; displayName?: string; bio?: string },
"avatarUrl" | "displayName" | "bio"
>;
ESLint flat config exampleโ
import typefest from "eslint-plugin-typefest";
export default [
{
plugins: { typefest },
rules: {
"typefest/prefer-type-fest-require-at-least-one": "error",
},
},
];
When not to use itโ
Disable this rule if published contracts must preserve existing alias names.
Package documentationโ
TypeFest package documentation:
Source file: source/require-at-least-one.d.ts
/**
Create a type that requires at least one of the given keys. The remaining keys are kept as is.
@example
```
import type {RequireAtLeastOne} from 'type-fest';
type Responder = {
text?: () => string;
json?: () => string;
secure?: boolean;
};
const responder: RequireAtLeastOne<Responder, 'text' | 'json'> = {
json: () => '{"message": "ok"}',
secure: true,
};
```
@category Object
*/
Rule catalog ID: R057