]> git.proxmox.com Git - pve-eslint.git/blame - eslint/docs/rules/no-unsafe-optional-chaining.md
import eslint 7.28.0
[pve-eslint.git] / eslint / docs / rules / no-unsafe-optional-chaining.md
CommitLineData
456be15e
TL
1# disallow use of optional chaining in contexts where the `undefined` value is not allowed (no-unsafe-optional-chaining)
2
3The 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:
4
5```js
6var obj = undefined;
7
81 in obj?.foo; // TypeError
9with (obj?.foo); // TypeError
10for (bar of obj?.foo); // TypeError
11bar instanceof obj?.foo; // TypeError
12const { bar } = obj?.foo; // TypeError
13```
14
15Also, parentheses limit the scope of short-circuiting in chains. For example:
16
17```js
18var obj = undefined;
19
20(obj?.foo)(); // TypeError
21(obj?.foo).bar; // TypeError
22```
23
24## Rule Details
25
26This 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.
27
28Examples of **incorrect** code for this rule:
29
30```js
31/*eslint no-unsafe-optional-chaining: "error"*/
32
33(obj?.foo)();
34
35(obj?.foo).bar;
36
37(foo?.()).bar;
38
39(foo?.()).bar();
40
41(obj?.foo ?? obj?.bar)();
42
43(foo || obj?.foo)();
44
45(obj?.foo && foo)();
46
47(foo ? obj?.foo : bar)();
48
49(foo, obj?.bar).baz;
50
51(obj?.foo)`template`;
52
53new (obj?.foo)();
54
55[...obj?.foo];
56
57bar(...obj?.foo);
58
591 in obj?.foo;
60
61bar instanceof obj?.foo;
62
63for (bar of obj?.foo);
64
65const { bar } = obj?.foo;
66
67[{ bar } = obj?.foo] = [];
68
69with (obj?.foo);
70
71class A extends obj?.foo {}
72
73var a = class A extends obj?.foo {};
74
75async function foo () {
76 const { bar } = await obj?.foo;
77 (await obj?.foo)();
78 (await obj?.foo).bar;
79}
80```
81
82Examples of **correct** code for this rule:
83
84```js
85/*eslint no-unsafe-optional-chaining: "error"*/
86
87(obj?.foo)?.();
88
89obj?.foo();
90
91(obj?.foo ?? bar)();
92
93obj?.foo.bar;
94
5422a9cc
TL
95obj.foo?.bar;
96
456be15e
TL
97foo?.()?.bar;
98
99(obj?.foo ?? bar)`template`;
100
101new (obj?.foo ?? bar)();
102
103var baz = {...obj?.foo};
104
105const { bar } = obj?.foo || baz;
106
107async function foo () {
108 const { bar } = await obj?.foo || baz;
109 (await obj?.foo)?.();
110 (await obj?.foo)?.bar;
111}
112```
113
114## Options
115
116This rule has an object option:
117
118- `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`.
119
120### disallowArithmeticOperators
121
122With this option set to `true` the rule is enforced for:
123
124- Unary operators: `-`, `+`
125- Arithmetic operators: `+`, `-`, `/`, `*`, `%`, `**`
126- Assignment operators: `+=`, `-=`, `/=`, `*=`, `%=`, `**=`
127
128Examples of additional **incorrect** code for this rule with the `{ "disallowArithmeticOperators": true }` option:
129
130```js
131/*eslint no-unsafe-optional-chaining: ["error", { "disallowArithmeticOperators": true }]*/
132
133+obj?.foo;
134-obj?.foo;
135
136obj?.foo + bar;
137obj?.foo - bar;
138obj?.foo / bar;
139obj?.foo * bar;
140obj?.foo % bar;
141obj?.foo ** bar;
142
143baz += obj?.foo;
144baz -= obj?.foo;
145baz /= obj?.foo;
146baz *= obj?.foo;
147baz %= obj?.foo;
148baz **= obj?.foo;
149
150async function foo () {
151 +await obj?.foo;
152 await obj?.foo + bar;
153 baz += await obj?.foo;
154}
155```