Index

no-unsafe-optional-chaining

不允许在不允许 undefined 值的上下文中使用可选链接

Recommended

配置文件 中使用来自 @eslint/jsrecommended 配置可以启用此规则

可选链(?.)表达式可以以返回值 undefined 提前结束。因此,将已求值的可选链表达式当作函数、对象、数字等处理,可能会导致 TypeError 或意外结果。例如:

🌐 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:

const obj = undefined;

1 in obj?.foo;  // TypeError
with (obj?.foo);  // TypeError
for (bar of obj?.foo);  // TypeError
bar instanceof obj?.foo;  // TypeError
const { bar } = obj?.foo;  // TypeError

另外,括号限制了链式短路的作用范围。例如:

🌐 Also, parentheses limit the scope of short-circuiting in chains. For example:

const obj = undefined;

(obj?.foo)(); // TypeError
(obj?.foo).bar; // TypeError

规则详情

🌐 Rule Details

此规则旨在检测某些情况下使用可选链无法防止运行时错误的情况。特别是,它会标记可选链表达式出现在短路到 undefined 后导致抛出 TypeError 的位置。

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

此规则的错误代码示例:

🌐 Examples of incorrect code for this rule:

在线运行
/*eslint no-unsafe-optional-chaining: "error"*/

(obj?.foo)();

(obj?.foo).bar;

(foo?.()).bar;

(foo?.()).bar();

(obj?.foo ?? obj?.bar)();

(foo || obj?.foo)();

(obj?.foo && foo)();

(foo ? obj?.foo : bar)();

(foo, obj?.bar).baz;

(obj?.foo)`template`;

new (obj?.foo)();

[...obj?.foo];

bar(...obj?.foo);

1 in obj?.foo;

bar instanceof obj?.foo;

for (bar of obj?.foo);

const { bar } = obj?.foo;

[{ bar } = obj?.foo] = [];

with (obj?.foo);

class A extends obj?.foo {}

const a = class A extends obj?.foo {};

async function foo () {
    const { bar } = await obj?.foo;
   (await obj?.foo)();
   (await obj?.foo).bar;
}

符合此规则的正确代码示例:

🌐 Examples of correct code for this rule:

在线运行
/*eslint no-unsafe-optional-chaining: "error"*/

(obj?.foo)?.();

obj?.foo();

(obj?.foo ?? bar)();

obj?.foo.bar;

obj.foo?.bar;

foo?.()?.bar;

(obj?.foo ?? bar)`template`;

new (obj?.foo ?? bar)();

const baz = {...obj?.foo};

const { bar } = obj?.foo || baz;

async function foo () {
  const { bar } = await obj?.foo || baz;
   (await obj?.foo)?.();
   (await obj?.foo)?.bar;
}

选项

🌐 Options

此规则有一个对象选项:

🌐 This rule has an object option:

  • disallowArithmeticOperators:禁止在可选链表达式上进行算术运算(默认 false)。如果设置为 true,此规则会警告在可选链表达式上进行算术运算,这可能导致 NaN

disallowArithmeticOperators

当此选项设置为 true 时,规则将强制执行以下内容:

🌐 With this option set to true the rule is enforced for:

  • 一元运算符:-+
  • 算术运算符:+-/*%**
  • 赋值运算符:+=-=/=*=%=**=

使用 { "disallowArithmeticOperators": true } 选项时,该规则的其他 错误 代码示例:

🌐 Examples of additional incorrect code for this rule with the { "disallowArithmeticOperators": true } option:

在线运行
/*eslint no-unsafe-optional-chaining: ["error", { "disallowArithmeticOperators": true }]*/

+obj?.foo;
-obj?.foo;

obj?.foo + bar;
obj?.foo - bar;
obj?.foo / bar;
obj?.foo * bar;
obj?.foo % bar;
obj?.foo ** bar;

baz += obj?.foo;
baz -= obj?.foo;
baz /= obj?.foo;
baz *= obj?.foo;
baz %= obj?.foo;
baz **= obj?.foo;

async function foo () {
  +await obj?.foo;
  await obj?.foo + bar;
  baz += await obj?.foo;
}

版本

此规则是在 ESLint v7.15.0 中引入。

资源