oxc-project/oxc · warning · OxcDiagnostic
Avoid unnecessary use of .{name}()
Error message
Avoid unnecessary use of .{name}() What it means
Diagnostic from the `no-useless-call` rule. It fires when `.call()` or `.apply()` adds nothing: the thisArg is null/undefined (or identical to the callee receiver) and apply's argument array is a plain spread of the same arguments a direct call would take. In strict-mode ES modules `this` is already undefined, so the indirection is pure overhead. Oxc detects it via `match_member_expression` on CallExpression whose callee property is `call`/`apply` on a plain function.
Source
Thrown at crates/oxc_linter/src/rules/eslint/no_useless_call.rs:14
use oxc_ast::{
AstKind,
ast::{CallExpression, ChainElement, Expression, MemberExpression},
match_member_expression,
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::ContentEq;
use oxc_span::Span;
use crate::{AstNode, context::LintContext, rule::Rule};
fn no_useless_call_diagnostic(name: &str, span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn(format!("Avoid unnecessary use of .{name}()"))
.with_help("Replace with a normal function invocation")
.with_label(span)
}
#[derive(Debug, Default, Clone)]
pub struct NoUselessCall;
declare_oxc_lint!(
/// ### What it does
///
/// Disallow unnecessary calls to `.call()` and `.apply()`
///
/// ### Why is this bad?
///
/// `Function.prototype.call()` and `Function.prototype.apply()` are slower than the normal function invocation.
///
/// This rule compares code statically to check whether or not thisArg is changed.
/// So if the code about thisArg is a dynamic expression, this rule cannot judge correctly.View on GitHub (pinned to e1e7af627c)
Solutions
- Replace `foo.call(null, 1, 2)` with a direct call `foo(1, 2)`.
- Replace `foo.apply(null, args)` with `foo(...args)`.
- If you rely on `this` binding, pass a meaningful thisArg or use `fn.bind(receiver)` once.
- Fix is often automatic: run `oxlint --fix` to rewrite the call.
Example fix
// before foo.call(null, 1, 2); foo.apply(undefined, [1, 2]); // after foo(1, 2); foo(1, 2);
Defensive patterns
Strategy: validation
Validate before calling
function isUselessCall(node) {
// before refactoring, detect .call(null/undefined, ...) patterns in review
return /^\.call\((null|undefined)/.test(snippet) || /^\.apply\((null|undefined),\s*\[/.test(snippet);
} Prevention
- Call functions directly; use spread `f(...args)` instead of apply.
- Reserve .call/.apply for actual this-binding with a real receiver.
- Run `oxlint --fix` in pre-commit to strip useless calls mechanically.
When it happens
Trigger: Calls like `foo.call(null)`, `foo.call(undefined, 1)`, `foo.apply(this, arguments)` in non-method contexts, or `obj.fn.call(obj, ...)` where the receiver equals the object itself. The rule matches MemberExpression callees named call/apply whose arguments provide no binding effect.
Common situations: Code ported from ES5 libraries that needed apply for variadic args before spread syntax; defensive `this` binding habits; bundled output from old transpilers that was hand-edited.
Related errors
- Unexpected var, use let or const instead.
- Unexpected `void` operator
- Unexpected use of `with` statement.
- Empty array binding pattern
- Empty object binding pattern
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/01c8baaf06d06e1f.
Report an issue: GitHub.