1 # disallow use of optional chaining in contexts where the `undefined` value is not allowed (no-unsafe-optional-chaining)
3 The optional chaining (`?.`) expression can short-circuit with a return value of `undefined`. Therefore, treating an evaluated optional chaining expression as a function, object, number, etc., can cause TypeError or unexpected results. For example:
8 1 in obj?.foo; // TypeError
9 with (obj?.foo); // TypeError
10 for (bar of obj?.foo); // TypeError
11 bar instanceof obj?.foo; // TypeError
12 const { bar } = obj?.foo; // TypeError
15 Also, parentheses limit the scope of short-circuiting in chains. For example:
20 (obj?.foo)(); // TypeError
21 (obj?.foo).bar; // TypeError
26 This rule aims to detect some cases where the use of optional chaining doesn't prevent runtime errors. In particular, it flags optional chaining expressions in positions where short-circuiting to `undefined` causes throwing a TypeError afterward.
28 Examples of **incorrect** code for this rule:
31 /*eslint no-unsafe-optional-chaining: "error"*/
41 (obj?.foo ?? obj?.bar)();
47 (foo ? obj?.foo : bar)();
61 bar instanceof obj?.foo;
63 for (bar of obj?.foo);
65 const { bar } = obj?.foo;
67 [{ bar } = obj?.foo] = [];
71 class A extends obj?.foo {}
73 var a = class A extends obj?.foo {};
75 async function foo () {
76 const { bar } = await obj?.foo;
82 Examples of **correct** code for this rule:
85 /*eslint no-unsafe-optional-chaining: "error"*/
97 (obj?.foo ?? bar)`template`;
99 new (obj?.foo ?? bar)();
101 var baz = {...obj?.foo};
103 const { bar } = obj?.foo || baz;
105 async function foo () {
106 const { bar } = await obj?.foo || baz;
107 (await obj?.foo)?.();
108 (await obj?.foo)?.bar;
114 This rule has an object option:
116 - `disallowArithmeticOperators`: Disallow arithmetic operations on optional chaining expressions (Default `false`). If this is `true`, this rule warns arithmetic operations on optional chaining expressions, which possibly result in `NaN`.
118 ### disallowArithmeticOperators
120 With this option set to `true` the rule is enforced for:
122 - Unary operators: `-`, `+`
123 - Arithmetic operators: `+`, `-`, `/`, `*`, `%`, `**`
124 - Assignment operators: `+=`, `-=`, `/=`, `*=`, `%=`, `**=`
126 Examples of additional **incorrect** code for this rule with the `{ "disallowArithmeticOperators": true }` option:
129 /*eslint no-unsafe-optional-chaining: ["error", { "disallowArithmeticOperators": true }]*/
148 async function foo () {
150 await obj?.foo + bar;
151 baz += await obj?.foo;