Skip to main content

prefer-ts-extras-is-property-present

Require isPropertyPresent from ts-extras in Array.prototype.filter callbacks instead of inline property-nullish checks.

Targeted pattern scopeโ€‹

This rule only inspects inline .filter(...) predicates that perform an explicit loose-null check against a single object property.

  • Inline property-nullish predicates inside .filter(...), including:
    • filter((item) => item.prop != null)
    • filter((item) => null != item.prop)

Named predicate references, multi-argument callbacks, and stricter equality checks are not matched.

What this rule reportsโ€‹

This rule reports inline filter predicates that check whether a single object property is not null (using loose equality, which also catches undefined) and can be normalized with isPropertyPresent.

Why this rule existsโ€‹

filter(isPropertyPresent('prop')) is the canonical ts-extras pattern for filtering out items where a specific property is null or undefined.

  • Filtering logic is consistent and composable across collections.
  • The property key is explicit in the function call, not embedded inside a callback expression.
  • Repeated inline != null callback expressions are removed.
  • isPropertyPresent is a proper type predicate that narrows element types in the resulting array to exclude both null and undefined.

โŒ Incorrectโ€‹

const titled = posts.filter((post) => post.title != null);

โœ… Correctโ€‹

import { isPropertyPresent } from "ts-extras";

const titled = posts.filter(isPropertyPresent("title"));

Behavior and migration notesโ€‹

  • isPropertyPresent('prop') checks item[prop] != null, which is true when the value is neither null nor undefined.
  • The autofix preserves the property name as a string literal.
  • Strict null checks (e.g., post.title !== null) are intentionally excluded โ€” those do not narrow away undefined.
  • Deep property access (e.g., post.meta.title != null) is intentionally excluded โ€” only single-level property checks are flagged.
  • Computed property access (e.g., post[key] != null) is intentionally excluded.

Additional examplesโ€‹

โŒ Incorrect โ€” reversed operandsโ€‹

const titled = posts.filter((post) => null != post.title);

โœ… Correct โ€” reversed operands fixedโ€‹

const titled = posts.filter(isPropertyPresent("title"));

ESLint flat config exampleโ€‹

import typefest from "eslint-plugin-typefest";

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

When not to use itโ€‹

Disable this rule if your filter callbacks intentionally combine property checks with additional logic, or if the property name is dynamic.

Package documentationโ€‹

ts-extras package documentation:

Source file: source/is-property-present.ts

/**
Returns a filter predicate that tests whether a given property key is present (non-nullable) on an object.

This is useful as a type guard in `Array.prototype.filter` to narrow the resulting array type by removing `null` and `undefined` property values.

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

interface Post {
title: string | null | undefined;
}

const posts: Post[] = [{ title: 'Hello' }, { title: null }];
const titledPosts = posts.filter(isPropertyPresent('title'));
//=> [{ title: 'Hello' }]
```

@category Type guard
*/

Rule catalog ID: R102

Further readingโ€‹