oxc-project/oxc · warning

Prefer a single `.flatMap(…)` over `.filter(…).flatMap(…)`.

Error message

Prefer a single `.flatMap(…)` over `.filter(…).flatMap(…)`.

What it means

This is a lint diagnostic from the oxlint rule `unicorn/prefer-array-flat-map`. It fires when code chains `.filter(...).flatMap(...)` on the same receiver, because the filter step can be inlined as an array literal returned by the flatMap callback, yielding a single `.flatMap(…)` call. The library throws it to steer developers toward simpler, more idiomatic array chaining.

Solutions

  1. Replace `.filter(predicate).flatMap(cb)` with a single `.flatMap(el => predicate(el) ? [...] : [])`, inlining the predicate condition into the callback.
  2. Apply the rule's provided auto-fix (it rewrites the chain, adding grouping parentheses around the predicate when used as a conditional test).
  3. Disable or downgrade `unicorn/prefer-array-flat-map` in .oxlintrc.json if the two-call form is preferred.

Example fix

// before
const ids = users.filter(u => u.active).flatMap(u => [u.id, u.parentId]);
// after
const ids = users.flatMap(u => u.active ? [u.id, u.parentId] : []);
Defensive patterns

Strategy: validation

Validate before calling

// oxlint config check before CI
// .oxlintrc.json
// { "rules": { "unicorn/prefer-array-flat-map": "warn" } }
// pre-commit: npx oxlint --fix --rule 'unicorn/prefer-array-flat-map':error

Prevention

When it happens

Trigger: oxlint detects `x.filter(fn).flatMap(cb)` where the filter callback name matches the flatMap callback's predicate name (simple_callback on the flatMap argument), the flatMap callback returns an array literal with more than one element (so inlining is beneficial), and the receiver is not a known non-indexed object (checked via is_known_non_indexed_receiver).

Common situations: Seen in everyday data-transformation code where developers filter then flatMap over arrays; also appears in migration runs when enabling unicorn presets, and in CI when new oxlint versions add this rule.

Understand the failure class

Background: "is deprecated and will be removed" — deprecation warnings for old API names, keywords, and options, and how to migrate before the removal release — this error's family across 29 libraries.

Related errors


AI-assisted analysis of oxc-project/oxc@12cb547351 (2026-09-20). Data as JSON: /api/errors/59708f083d8bd3da. Report an issue: GitHub.

Appendix: source

Thrown at crates/oxc_linter/src/rules/unicorn/prefer_array_flat_map.rs:163

        && member.property.name == "flatMap"
        && let Expression::CallExpression(filter) = member.object.get_inner_expression()
        && !filter.optional
        && filter.type_arguments.is_none()
        && filter.arguments.len() == 1
        && let Expression::StaticMemberExpression(filter_member) =
            filter.callee.get_inner_expression()
        && !filter_member.optional
        && filter_member.property.name == "filter"
        && !has_optional_chain(&filter_member.object)
        && !ctx.has_comments_between(call.span)
        && let Some((filter_name, predicate)) = simple_callback(&filter.arguments[0])
        && let Some((map_name, mapped)) = simple_callback(&call.arguments[0])
        && filter_name == map_name
        && matches!(mapped.without_parentheses(), Expression::ArrayExpression(array) if array.elements.len() > 1)
        && !is_known_non_indexed_receiver(&filter_member.object, ctx)
    {
        ctx.diagnostic_with_suggestion(
            OxcDiagnostic::warn("Prefer a single `.flatMap(…)` over `.filter(…).flatMap(…)`.")
                .with_label(member.property.span),
            |fixer| {
                let receiver = fixer.source_range(filter_member.object.span());
                let predicate_text = fixer.source_range(predicate.span());
                // These expressions need grouping when used as the test of a conditional.
                let predicate_text = if matches!(
                    predicate,
                    Expression::ArrowFunctionExpression(_)
                        | Expression::AssignmentExpression(_)
                        | Expression::ClassExpression(_)
                        | Expression::ConditionalExpression(_)
                        | Expression::FunctionExpression(_)
                        | Expression::ObjectExpression(_)
                        | Expression::SequenceExpression(_)
                        | Expression::TSAsExpression(_)
                        | Expression::TSNonNullExpression(_)
                        | Expression::TSSatisfiesExpression(_)
                        | Expression::TSTypeAssertion(_)

View on GitHub (pinned to 12cb547351)