# 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.

{/* Generated by src/codegen/lint-rule-docs.ts. Do not edit this section. */}

## Configure

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

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

Every option, set to its default:

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

{/* End of the generated section. */}

## Examples

Reported:

{/* bad {"count": 4} */}
```js
const { name } = user?.profile;

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

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

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

Not reported:

{/* good */}
```js
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:

{/* bad */}
```js
const city = (user?.address).city;
```

{/* good */}
```js
const city = user?.address.city;
```

## Options

| Option | Default | What it does |
| --- | --- | --- |
| `disallowArithmeticOperators` | `false` | Also report an optional chain in arithmetic, such as `a?.b + 1`, `-a?.b`, or `x += a?.b`, where `undefined` gives `NaN`. |

{/* bad {"options": [{"disallowArithmeticOperators": true}]} */}
```js
const total = cart?.subtotal + shipping;
```

{/* good {"options": [{"disallowArithmeticOperators": true}]} */}
```js
const total = (cart?.subtotal ?? 0) + shipping;
```
