
Security News
n8n Tops 2025 JavaScript Rising Stars as Workflow Platforms Gain Momentum
n8n led JavaScript Rising Stars 2025 by a wide margin, with workflow platforms seeing the largest growth across categories.
eslint-plugin-no-optional-call
Advanced tools
An ESLint plugin to disable the use of the optional-call operator.
The no-optional-call ESLint plugin provides a single rule (non-configurable) that disallows any usage of the ?.( optional-call form.
Unlike the related ?. / ?.[ optional-chaining operators (which are quite useful), the ?.( optional-call operator is total junk, and should never have been added to the language -- at least, not how it was designed.
This plugin allows you to ensure that it never creeps into your project by accident.
The supposed usage of this operator is like this:
obj?.func?.(42);
The first ?. is optional-chaining (which is fine!), but the second ?.( is an optional-call (which is bad). But importantly, this is not necessarily an object/method feature, as the optional-call can be used with a single identifier like this:
func?.(42);
In both cases, here's the equivalent code this ?.( operator purports to replace:
if (obj.func != null) {
obj.func(42);
}
if (func != null) {
func(42);
}
The usage of != null here is on purpose. It's non-nullish checking, meaning that it avoids null and undefined, but no other values.
WARNING: a common misconception is that the ?.( operator is actually intended for replacing this kind of code (which is a bit more common/relaxed):
obj.func && obj.func(42);
// or:
if (obj.func) {
obj.func(42);
}
// **********
func && func(42);
// or:
if (func) {
func(42);
}
These are subtly but importantly different than the previous != null forms. That's the first gotcha! If your existing code has relied on avoiding falsy values in obj.func / func other than the nullish values (null, undefined), such as false, "", NaN, or 0, then switching to ?.( will break your code, since the ?.( operator only stops at null and undefined values.
Oops!
But here's what's worse, what really dooms this ?.( feature, and why you should avoid ever using it in your programs (and rely on this plugin to ensure you don't).
This operator looks like what it's doing is providing a "safe call" type of operator (which exists in other programming languages). It seems like it's making sure that the value is callable (is actually a function) before calling it.
To the untrained eye that's not paying close attention, ?.( looks like it should be doing this:
if (typeof obj.func == "function") {
obj.func(42);
}
if (typeof func == "function") {
func(42);
}
But it doesn't! It only avoids null / undefined values.
If obj.func / func holds any non-function truthy value (strings, numbers, objects, arrays, dates, regular expressions, etc), then ?.( will attempt to execute call that value as if it was a function, which of course will fail because none of those are functions.
In other words, all falsy values except null and undefined, and all truthy values besides functions themselves, are all traps where the ?.( operator is going to fall over and break your program.
I know a bunch of you are yelling at me that TypeScript solves this problem, because it makes sure all those other value-types are not in obj.func / func.
Here's my simple rebuttal: I call utter B.S. on the design of any JS feature which is full of (technically, an infinite number of) gotcha footguns by itself, and only operates sensibly if you also use TypeScript.
It'd be fine if TypeScript wanted to add this feature. Use it there to your heart's content! But if you're writing only JS, you should never, ever, ever, ever... use this ?.( feature.
To use no-optional-call, load it as a plugin into ESLint and configure the rules as desired.
.eslintrc.jsonTo load the plugin and enable its rules via a local or global .eslintrc.json configuration file:
"plugins": [
"no-optional-call"
],
"rules": {
"no-optional-call/default": "error"
}
package.jsonTo load the plugin and enable its rules via a project's package.json:
"eslintConfig": {
"plugins": [
"no-optional-call"
],
"rules": {
"no-optional-call/default": "error"
}
}
To load the plugin and enable its rules via ESLint CLI parameters, use --plugin and --rule flags:
eslint .. --plugin='no-optional-call' --rule='no-optional-call/default: error' ..
To use this plugin in Node.js with the ESLint API, require the npm module, and then (for example) pass the rule's definition to Linter#defineRule(..), similar to:
var noOptionalCall = require("eslint-plugin-no-optional-call");
// ..
var eslinter = new (require("eslint").Linter)();
eslinter.defineRule("no-optional-call/default",noOptionalCall.rules.default);
Then lint some code like this:
eslinter.verify(".. some code ..",{
rules: {
"no-optional-call/default": "error",
}
});
Once the plugin is loaded, the rule can be configured using inline code comments if desired, such as:
/* eslint "no-optional-call/default": "error" */
To use this plugin with a global install of ESLint (recommended):
npm install -g eslint-plugin-no-optional-call
To use this plugin with a local install of ESLint:
npm install eslint-plugin-no-optional-call
All code and documentation are (c) 2022 Kyle Simpson and released under the MIT License. A copy of the MIT License is also included.
NOTE: This package was heavily inspired by eslint-plugin-no-pipe by @arendjr.
FAQs
An ESLint plugin to disable the use of the optional-call operator.
We found that eslint-plugin-no-optional-call demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
n8n led JavaScript Rising Stars 2025 by a wide margin, with workflow platforms seeing the largest growth across categories.

Security News
The U.S. government is rolling back software supply chain mandates, shifting from mandatory SBOMs and attestations to a risk-based approach.

Security News
crates.io adds a Security tab backed by RustSec advisories and narrows trusted publishing paths to reduce common CI publishing risks.