优先使用可选链
强制使用简洁的可选链表达式,而不是链式逻辑与、取反逻辑或或空对象。
在 "plugin:@typescript-eslint/stylistic-type-checked"
中扩展 ESLint 配置 可以启用此规则。
此规则报告的一些问题可以通过 --fix
ESLint 命令行选项 自动修复。
此规则报告的一些问题可以通过编辑器 建议 手动修复。
此规则需要 类型信息 才能运行。
?.
可选链表达式在对象为 null
或 undefined
时提供 undefined
。因为可选链运算符仅在属性值为 null
或 undefined
时才进行链式操作,所以它比依赖逻辑与运算符链式操作 &&
更安全;逻辑与运算符链式操作在任何真值上都进行链式操作。使用 ?.
可选链式操作通常也比 &&
真值检查更少代码。
此规则报告代码中可以使用 ?.
可选链式操作安全替换 &&
运算符的地方。
module.exports = {
"rules": {
"@typescript-eslint/prefer-optional-chain": "error"
}
};
在游乐场中尝试此规则 ↗
示例
- ❌ 错误
- ✅ 正确
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;
在游乐场中打开foo?.a?.b?.c;
foo?.['a']?.b?.c;
foo?.a?.b?.method?.();
foo?.a?.b?.c?.d?.e;
!foo?.bar;
!foo?.[bar];
!foo?.bar?.baz?.();
在游乐场中打开选项
此规则接受以下选项
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 = [
{
checkAny: true,
checkUnknown: true,
checkString: true,
checkNumber: true,
checkBoolean: true,
checkBigInt: true,
requireNullish: false,
allowPotentiallyUnsafeFixesThatModifyTheReturnTypeIKnowWhatImDoing: false,
},
];
在以下描述的上下文中,“松散布尔”操作数是任何隐式将值强制转换为布尔值的运算符。具体来说,非运算符(!loose
)的参数或逻辑表达式中的裸值(loose && looser
)。
allowPotentiallyUnsafeFixesThatModifyTheReturnTypeIKnowWhatImDoing
当此选项为 true
时,该规则将为表达式返回类型将发生变化的情况提供自动修复程序。例如,对于表达式 !foo || foo.bar
,表达式的返回类型为 true | T
,但是对于等效的可选链式操作 foo?.bar
,表达式的返回类型为 undefined | T
。因此,将代码从逻辑表达式更改为可选链式操作表达式已更改了表达式的类型。
在某些情况下,这种区别可能很重要 - 这就是为什么这些修复程序被认为是不安全的 - 它们可能会破坏构建!例如,在以下代码中
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);
在游乐场中打开这种代码风格并不常见 - 这意味着将此选项设置为true
应该在大多数代码库中是安全的。但是,由于其不安全的性质,我们将其默认设置为false
。我们提供了此选项是为了方便,因为它增加了规则涵盖的自动修复案例。如果您将选项设置为true
,则您和您的团队有责任确保每个修复都是正确且安全的,并且不会破坏构建。
当此选项为false
时,不安全的案例将提供建议修复程序而不是自动修复程序 - 这意味着您可以使用 IDE 工具手动应用修复程序。
checkAny
当此选项为true
时,该规则将在检查“松散布尔”操作数时检查类型为any
的操作数。
- ❌ 对于
checkAny: true
不正确 - ✅ 对于
checkAny: false
正确
checkUnknown
当此选项为true
时,该规则将在检查“松散布尔”操作数时检查类型为unknown
的操作数。
- ❌ 对于
checkUnknown: true
不正确 - ✅ 对于
checkUnknown: false
正确
checkString
当此选项为true
时,该规则将在检查“松散布尔”操作数时检查类型为string
的操作数。
- ❌ 对于
checkString: true
不正确 - ✅ 对于
checkString: false
正确
checkNumber
当此选项为true
时,该规则将在检查“松散布尔”操作数时检查类型为number
的操作数。
- ❌ 对于
checkNumber: true
不正确 - ✅ 对于
checkNumber: false
正确
checkBoolean
当此选项为true
时,该规则将在检查“松散布尔”操作数时检查类型为boolean
的操作数。
此规则有意忽略以下情况
declare const x: false | { a: string };
x && x.a;
!x || x.a;
布尔表达式排除了非空假值情况 - 因此将链转换为 x?.a
会引入类型错误。
- ❌ 对于
checkBoolean: true
不正确 - ✅ 对于
checkBoolean: false
正确
checkBigInt
当此选项为 true
时,该规则将在检查“松散布尔”操作数时检查类型为 bigint
的操作数。
- ❌ 对于
checkBigInt: true
不正确 - ✅ 对于
checkBigInt: false
正确
requireNullish
当此选项为 true
时,该规则将在检查“松散布尔”操作数时跳过未用 null
和/或 undefined
类型化的操作数。
- ❌ 对于
requireNullish: true
不正确 - ✅ 对于
requireNullish: true
正确
何时不使用它
如果您的项目没有被准确地类型化,例如,如果它正在转换为 TypeScript 或容易受到 控制流分析中的权衡 的影响,那么可能难以为此规则启用特别不安全的代码区域。您可能考虑使用 ESLint 禁用注释 来处理这些特定情况,而不是完全禁用此规则。
进一步阅读
类型检查的 lint 规则比传统的 lint 规则更强大,但也需要配置 类型检查的 lint。如果您在启用类型检查的规则后遇到性能下降,请参阅 性能故障排除。