Skip to main content

prefer-ts-extras-not

Require not from ts-extras over inline negated predicate callbacks in filter calls.

Targeted pattern scopeโ€‹

This rule focuses on direct .filter(...) callbacks that negate a predicate and can be migrated to not(predicate) with deterministic fixes.

  • Inline negated predicate callbacks in .filter(...) that can use not(predicate).
  • array.filter((value) => !predicate(value))

Alias indirection, wrapper helpers, and non-canonical call shapes are excluded to keep not(predicate) migrations safe.

What this rule reportsโ€‹

This rule reports .filter(...) call sites when not(predicate) is the intended replacement.

  • Inline negated predicate callbacks in .filter(...) that can use not(predicate).
  • array.filter((value) => !predicate(value))

Why this rule existsโ€‹

not(predicate) communicates intent directly and preserves predicate-based typing in a reusable helper.

โŒ Incorrectโ€‹

const activeUsers = users.filter((user) => !isArchived(user));

โœ… Correctโ€‹

const activeUsers = users.filter(not(isArchived));

Behavior and migration notesโ€‹

  • not(predicate) preserves predicate inversion intent in one reusable helper.
  • This rule targets inline negation wrappers inside filter callbacks.
  • Callbacks that do extra work beyond predicate negation should be reviewed manually.

Additional examplesโ€‹

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

const active = users.filter((user) => !isArchived(user));

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

const active = users.filter(not(isArchived));

โœ… Correct โ€” Repository-wide usageโ€‹

const nonEmpty = values.filter(not(isEmptyValue));

ESLint flat config exampleโ€‹

import typefest from "eslint-plugin-typefest";

export default [
{
plugins: { typefest },
rules: {
"typefest/prefer-ts-extras-not": "error",
},
},
];

When not to use itโ€‹

Disable this rule if your codebase requires explicit inline callback bodies for readability.

Package documentationโ€‹

ts-extras package documentation:

Source file: source/not.ts

/**
Invert a type predicate function.

This utility allows you to create the inverse of any type guard function, using TypeScript's `Exclude` utility type to properly narrow types.

@example
```
import {not} from 'ts-extras';

const isNullish = (value: unknown): value is null | undefined => value == null;

const isNotNullish = not(isNullish);

const values = [1, null, 2, undefined, 3];
const defined = values.filter(isNotNullish);
//=> [1, 2, 3]
// with type number[]

// Works with any type guard
const isString = (value: unknown): value is string => typeof value === 'string';

const isNotString = not(isString);

declare const mixedValue: string | number | boolean;
if (isNotString(mixedValue)) {
mixedValue;
//=> number | boolean
}
```

@note TypeScript may fail to narrow types in nested branches, with mutated variables, or when using `Exclude` with complex union types. See:
- https://github.com/microsoft/TypeScript/issues/44901
- https://github.com/microsoft/TypeScript/issues/43589

@category Type guard
*/

Rule catalog ID: R025

Further readingโ€‹

Adoption resourcesโ€‹