]> git.proxmox.com Git - pve-eslint.git/blame - eslint/docs/rules/no-unsafe-optional-chaining.md
buildsys: change upload dist to bullseye
[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
95foo?.()?.bar;
96
97(obj?.foo ?? bar)`template`;
98
99new (obj?.foo ?? bar)();
100
101var baz = {...obj?.foo};
102
103const { bar } = obj?.foo || baz;
104
105async function foo () {
106 const { bar } = await obj?.foo || baz;
107 (await obj?.foo)?.();
108 (await obj?.foo)?.bar;
109}
110```
111
112## Options
113
114This rule has an object option:
115
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`.
117
118### disallowArithmeticOperators
119
120With this option set to `true` the rule is enforced for:
121
122- Unary operators: `-`, `+`
123- Arithmetic operators: `+`, `-`, `/`, `*`, `%`, `**`
124- Assignment operators: `+=`, `-=`, `/=`, `*=`, `%=`, `**=`
125
126Examples of additional **incorrect** code for this rule with the `{ "disallowArithmeticOperators": true }` option:
127
128```js
129/*eslint no-unsafe-optional-chaining: ["error", { "disallowArithmeticOperators": true }]*/
130
131+obj?.foo;
132-obj?.foo;
133
134obj?.foo + bar;
135obj?.foo - bar;
136obj?.foo / bar;
137obj?.foo * bar;
138obj?.foo % bar;
139obj?.foo ** bar;
140
141baz += obj?.foo;
142baz -= obj?.foo;
143baz /= obj?.foo;
144baz *= obj?.foo;
145baz %= obj?.foo;
146baz **= obj?.foo;
147
148async function foo () {
149 +await obj?.foo;
150 await obj?.foo + bar;
151 baz += await obj?.foo;
152}
153```