]> git.proxmox.com Git - pve-eslint.git/blob - 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
1 # disallow use of optional chaining in contexts where the `undefined` value is not allowed (no-unsafe-optional-chaining)
2
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:
4
5 ```js
6 var obj = undefined;
7
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
13 ```
14
15 Also, parentheses limit the scope of short-circuiting in chains. For example:
16
17 ```js
18 var obj = undefined;
19
20 (obj?.foo)(); // TypeError
21 (obj?.foo).bar; // TypeError
22 ```
23
24 ## Rule Details
25
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.
27
28 Examples 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
53 new (obj?.foo)();
54
55 [...obj?.foo];
56
57 bar(...obj?.foo);
58
59 1 in obj?.foo;
60
61 bar instanceof obj?.foo;
62
63 for (bar of obj?.foo);
64
65 const { bar } = obj?.foo;
66
67 [{ bar } = obj?.foo] = [];
68
69 with (obj?.foo);
70
71 class A extends obj?.foo {}
72
73 var a = class A extends obj?.foo {};
74
75 async function foo () {
76 const { bar } = await obj?.foo;
77 (await obj?.foo)();
78 (await obj?.foo).bar;
79 }
80 ```
81
82 Examples of **correct** code for this rule:
83
84 ```js
85 /*eslint no-unsafe-optional-chaining: "error"*/
86
87 (obj?.foo)?.();
88
89 obj?.foo();
90
91 (obj?.foo ?? bar)();
92
93 obj?.foo.bar;
94
95 foo?.()?.bar;
96
97 (obj?.foo ?? bar)`template`;
98
99 new (obj?.foo ?? bar)();
100
101 var baz = {...obj?.foo};
102
103 const { bar } = obj?.foo || baz;
104
105 async function foo () {
106 const { bar } = await obj?.foo || baz;
107 (await obj?.foo)?.();
108 (await obj?.foo)?.bar;
109 }
110 ```
111
112 ## Options
113
114 This 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
120 With this option set to `true` the rule is enforced for:
121
122 - Unary operators: `-`, `+`
123 - Arithmetic operators: `+`, `-`, `/`, `*`, `%`, `**`
124 - Assignment operators: `+=`, `-=`, `/=`, `*=`, `%=`, `**=`
125
126 Examples 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
134 obj?.foo + bar;
135 obj?.foo - bar;
136 obj?.foo / bar;
137 obj?.foo * bar;
138 obj?.foo % bar;
139 obj?.foo ** bar;
140
141 baz += obj?.foo;
142 baz -= obj?.foo;
143 baz /= obj?.foo;
144 baz *= obj?.foo;
145 baz %= obj?.foo;
146 baz **= obj?.foo;
147
148 async function foo () {
149 +await obj?.foo;
150 await obj?.foo + bar;
151 baz += await obj?.foo;
152 }
153 ```