Skip to content
NewBun 1.4.5 is out. Release notes
AphrodyBun

Linter · Rules

no-unsafe-optional-chaining

Disallow optional chaining where undefined throws an error

user?.profile is undefined when user is missing. If you then destructure that result, spread it into an array or a call, loop over it, call it, or read a property of it, you get the TypeError that ?. was there to prevent.

The same goes for the right side of in and instanceof, and for extends. The rule also finds a chain behind await, &&, or ? :, and on the right of || or ??.

This rule is on by default.

Configure

On by default as an error. To turn it off:

bunfig.toml
[lint.rules]
"no-unsafe-optional-chaining" = "off" # or "warn"

Every option, set to its default:

bunfig.toml
[lint.rules]
"no-unsafe-optional-chaining" = ["error", {
  disallowArithmeticOperators = false,
}]

Examples

Reported:

const { name } = user?.profile;

for (const item of order?.items) {
  ship(item);
}

const all = [...order?.items];

const data = (await response?.json()).data;

Not reported:

const { name } = user?.profile ?? {};

for (const item of order?.items ?? []) {
  ship(item);
}

const all = [...(order?.items ?? [])];

const data = (await response?.json())?.data;

Parentheses end the chain. Without them, everything after ?. is skipped when user is missing:

const city = (user?.address).city;
const city = user?.address.city;

Options

OptionDefaultWhat it does
disallowArithmeticOperatorsfalseAlso report an optional chain in arithmetic, such as a?.b + 1, -a?.b, or x += a?.b, where undefined gives NaN.
const total = cart?.subtotal + shipping;
const total = (cart?.subtotal ?? 0) + shipping;