Skip to main content

prefer-optional-chain

Enforce using concise optional chain expressions instead of chained logical ands, negated logical ors, or empty objects.

🔧

此规则报告的一些问题可通过 --fix ESLint 命令行选项自动修复

💡

此规则报告的一些问题可以通过编辑器 建议 手动修复。

💭

该规则需要 类型信息 才能运行,但这会带来性能方面的权衡。

如果对象是 nullundefined,则 ?. 可选链表达式提供 undefined。因为可选链运算符仅在属性值为 nullundefined 时才会链接,所以它比依赖逻辑 AND 运算符链接 && 安全得多;它依赖于任何真值。使用 ?. 可选链接的代码通常比 && 真实性检查的代码要少。

¥?. optional chain expressions provide undefined if an object is null or undefined. Because the optional chain operator only chains when the property value is null or undefined, it is much safer than relying upon logical AND operator chaining &&; which chains on any truthy value. It is also often less code to use ?. optional chaining than && truthiness checks.

此规则报告 && 关键字作为类型注释的明确使用。

¥This rule reports on code where an && operator can be safely replaced with ?. optional chaining.

eslint.config.mjs
export default tseslint.config({
rules: {
"@typescript-eslint/prefer-optional-chain": "error"
}
});

在线运行试试这个规则 ↗

示例

¥Examples

foo && foo.a && foo.a.b && foo.a.b.c;
foo && foo['a'] && foo['a'].b && foo['a'].b.c;
foo && foo.a && foo.a.b && foo.a.b.method && foo.a.b.method();

// With empty objects
(((foo || {}).a || {}).b || {}).c;
(((foo || {})['a'] || {}).b || {}).c;

// With negated `or`s
!foo || !foo.bar;
!foo || !foo[bar];
!foo || !foo.bar || !foo.bar.baz || !foo.bar.baz();

// this rule also supports converting chained strict nullish checks:
foo &&
foo.a != null &&
foo.a.b !== null &&
foo.a.b.c != undefined &&
foo.a.b.c.d !== undefined &&
foo.a.b.c.d.e;
Open in Playground

选项

该规则接受以下选项:

type Options = [
{
/** Allow autofixers that will change the return type of the expression. This option is considered unsafe as it may break the build. */
allowPotentiallyUnsafeFixesThatModifyTheReturnTypeIKnowWhatImDoing?: boolean;
/** Check operands that are typed as `any` when inspecting "loose boolean" operands. */
checkAny?: boolean;
/** Check operands that are typed as `bigint` when inspecting "loose boolean" operands. */
checkBigInt?: boolean;
/** Check operands that are typed as `boolean` when inspecting "loose boolean" operands. */
checkBoolean?: boolean;
/** Check operands that are typed as `number` when inspecting "loose boolean" operands. */
checkNumber?: boolean;
/** Check operands that are typed as `string` when inspecting "loose boolean" operands. */
checkString?: boolean;
/** Check operands that are typed as `unknown` when inspecting "loose boolean" operands. */
checkUnknown?: boolean;
/** Skip operands that are not typed with `null` and/or `undefined` when inspecting "loose boolean" operands. */
requireNullish?: boolean;
},
];

const defaultOptions: Options = [
{
allowPotentiallyUnsafeFixesThatModifyTheReturnTypeIKnowWhatImDoing: false,
checkAny: true,
checkBigInt: true,
checkBoolean: true,
checkNumber: true,
checkString: true,
checkUnknown: true,
requireNullish: false,
},
];

¥Options

在下面的描述中,"松散布尔值" 操作数是任何将值隐式强制转换为布尔值的操作数。具体来说,非运算符(!loose)的参数或逻辑表达式(loose && looser)中的裸值。

¥In the context of the descriptions below a "loose boolean" operand is any operand that implicitly coerces the value to a boolean. Specifically the argument of the not operator (!loose) or a bare value in a logical expression (loose && looser).

allowPotentiallyUnsafeFixesThatModifyTheReturnTypeIKnowWhatImDoing

Allow autofixers that will change the return type of the expression. This option is considered unsafe as it may break the build. Default: false.

当此选项为 true 时,规则将为表达式的返回类型会发生变化的情况提供自动修复程序。例如,对于表达式 !foo || foo.bar,表达式的返回类型是 true | T,但是对于等效的可选链 foo?.bar,表达式的返回类型是 undefined | T。因此,将代码从逻辑表达式更改为可选链表达式已经改变了表达式的类型。

¥When this option is true, the rule will provide an auto-fixer for cases where the return type of the expression would change. For example for the expression !foo || foo.bar the return type of the expression is true | T, however for the equivalent optional chain foo?.bar the return type of the expression is undefined | T. Thus changing the code from a logical expression to an optional chain expression has altered the type of the expression.

在某些情况下,这种区别可能很重要 - 这就是为什么这些修复程序被认为是不安全的原因 - 它们可能会破坏构建!例如在以下代码中:

¥In some cases this distinction may matter - which is why these fixers are considered unsafe - they may break the build! For example in the following code:

declare const foo: { bar: boolean } | null | undefined;
declare function acceptsBoolean(arg: boolean): void;

// ✅ typechecks succesfully as the expression only returns `boolean`
acceptsBoolean(foo != null && foo.bar);

// ❌ typechecks UNSUCCESSFULLY as the expression returns `boolean | undefined`
acceptsBoolean(foo?.bar);
Open in Playground

这种代码样式并不常见 - 这意味着将此选项设置为 true 在大多数代码库中应该是安全的。但是,由于其不安全的性质,我们将其默认为 false。为了方便起见,我们提供了此选项,因为它增加了规则涵盖的自动修复案例。如果你将选项设置为 true,则你和你的团队有责任确保每个修复都是正确和安全的,并且不会破坏构建。

¥This style of code isn't super common - which means having this option set to true should be safe in most codebases. However we default it to false due to its unsafe nature. We have provided this option for convenience because it increases the autofix cases covered by the rule. If you set option to true the onus is entirely on you and your team to ensure that each fix is correct and safe and that it does not break the build.

当此选项为 false 时,不安全的情况将提供建议修复程序而不是自动修复程序 - 意味着你可以使用 IDE 工具手动应用修复。

¥When this option is false unsafe cases will have suggestion fixers provided instead of auto-fixers - meaning you can manually apply the fix using your IDE tooling.

checkAny

Check operands that are typed as any when inspecting "loose boolean" operands. Default: true.

带有 { checkAny: true } 的此规则的代码示例:

¥Examples of code for this rule with { checkAny: true }:

declare const thing: any;

thing && thing.toString();
Open in Playground

checkUnknown

Check operands that are typed as unknown when inspecting "loose boolean" operands. Default: true.

带有 { checkUnknown: true } 的此规则的代码示例:

¥Examples of code for this rule with { checkUnknown: true }:

declare const thing: unknown;

thing && thing.toString();
Open in Playground

checkString

Check operands that are typed as string when inspecting "loose boolean" operands. Default: true.

带有 { checkString: true } 的此规则的代码示例:

¥Examples of code for this rule with { checkString: true }:

declare const thing: string;

thing && thing.toString();
Open in Playground

checkNumber

Check operands that are typed as number when inspecting "loose boolean" operands. Default: true.

带有 { checkNumber: true } 的此规则的代码示例:

¥Examples of code for this rule with { checkNumber: true }:

declare const thing: number;

thing && thing.toString();
Open in Playground

checkBoolean

Check operands that are typed as boolean when inspecting "loose boolean" operands. Default: true.

注意

此规则有意忽略以下情况:

¥This rule intentionally ignores the following case:

declare const x: false | { a: string };
x && x.a;
!x || x.a;

布尔表达式缩小了非空的假值情况 - 因此将链转换为 x?.a 会引入类型错误。

¥The boolean expression narrows out the non-nullish falsy cases - so converting the chain to x?.a would introduce a type error.

带有 { checkBoolean: true } 的此规则的代码示例:

¥Examples of code for this rule with { checkBoolean: true }:

declare const thing: true;

thing && thing.toString();
Open in Playground

checkBigInt

Check operands that are typed as bigint when inspecting "loose boolean" operands. Default: true.

带有 { checkBigInt: true } 的此规则的代码示例:

¥Examples of code for this rule with { checkBigInt: true }:

declare const thing: bigint;

thing && thing.toString();
Open in Playground

requireNullish

Skip operands that are not typed with null and/or undefined when inspecting "loose boolean" operands. Default: false.

带有 { requireNullish: true } 的此规则的代码示例:

¥Examples of code for this rule with { requireNullish: true }:

declare const thing1: string | null;
thing1 && thing1.toString();
Open in Playground

何时不使用它

¥When Not To Use It

如果你的项目类型不准确,例如,如果它正在转换为 TypeScript 或易受 控制流分析中的权衡 影响,则可能很难为特别非类型安全的代码区域启用此规则。你可以考虑在这些特定情况下使用 ESLint 禁用注释,而不是完全禁用此规则。

¥If your project is not accurately typed, such as if it's in the process of being converted to TypeScript or is susceptible to trade-offs in control flow analysis, it may be difficult to enable this rule for particularly non-type-safe areas of code. You might consider using ESLint disable comments for those specific situations instead of completely disabling this rule.

进一步阅读

¥Further Reading


Type checked lint rules are more powerful than traditional lint rules, but also require configuring type checked linting.

See Troubleshooting > Linting with Type Information > Performance if you experience performance degradations after enabling type checked rules.

'## 资源'