Skip to main content

prefer-nullish-coalescing

强制使用空值合并运算符,而不是逻辑赋值或链接.

💡

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

💭

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

?? 空值合并运行时运算符允许在处理 nullundefined 时提供默认值。因为空值合并运算符仅在原始值为 nullundefined 时合并,所以它比依赖逻辑或运算符链接 ||(在任何假值上合并)要安全得多。

¥The ?? nullish coalescing runtime operator allows providing a default value when dealing with null or undefined. Because the nullish coalescing operator only coalesces when the original value is null or undefined, it is much safer than relying upon logical OR operator chaining ||, which coalesces on any falsy value.

此规则报告你何时可以考虑更换:

¥This rule reports when you may consider replacing:

  • 带有 ??|| 运算符

    ¥An || operator with ??

  • 带有 ??=||= 运算符

    ¥An ||= operator with ??=

  • 三元表达式 (?:) 等同于 ||????

    ¥Ternary expressions (?:) that are equivalent to || or ?? with ??

  • 可以安全地用 ??= 替换的赋值表达式 (=)

    ¥Assignment expressions (=) that can be safely replaced by ??=

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

在线运行试试这个规则 ↗

示例

¥Examples

declare const a: string | null;
declare const b: string | null;

const c = a || b;

declare let foo: { a: string } | null;
declare function makeFoo(): { a: string };

function lazyInitializeFooByTruthiness() {
if (!foo) {
foo = makeFoo();
}
}

function lazyInitializeFooByNullCheck() {
if (foo == null) {
foo = makeFoo();
}
}
Open in Playground
提醒

如果未启用 strictNullChecks,此规则将无法按预期工作。

¥This rule will not work as expected if strictNullChecks is not enabled.

选项

该规则接受以下选项:

type Options = [
{
/** 除非将其设置为 `true`,否则规则将在每个 `tsconfig.json` 没有将 `strictNullChecks` 编译器选项(或 `strict`)设置为 `true` 的文件上出错。 */
allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing?: boolean;
/** 是否忽略 `Boolean` 构造函数的参数 */
ignoreBooleanCoercion?: boolean;
/** 是否忽略位于条件测试中的案例。 */
ignoreConditionalTests?: boolean;
/** 是否忽略可以通过使用空值合并运算符简化的任何 if 语句。 */
ignoreIfStatements?: boolean;
/** 是否忽略任何属于混合逻辑表达式(带有 `&&`)的逻辑或表达式。 */
ignoreMixedLogicalExpressions?: boolean;
/** 是否忽略所有(`true`)或部分(具有属性的对象)原始类型。 */
ignorePrimitives?: /**
* 是否忽略所有(`true`)或部分(具有属性的对象)原始类型。
* 可以忽略哪些原始类型。
*/
| {
/** 忽略 bigint 原始类型。 */
bigint?: boolean;
/** 忽略 boolean 原始类型。 */
boolean?: boolean;
/** 忽略 number 原始类型。 */
number?: boolean;
/** 忽略 string 原始类型。 */
string?: boolean;
[k: string]: unknown;
}
/** 忽略所有原始类型。 */
| true;
/** 是否忽略任何可以通过使用空值合并运算符简化的三元表达式。 */
ignoreTernaryTests?: boolean;
},
];

const defaultOptions: Options = [
{
allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing: false,
ignoreBooleanCoercion: false,
ignoreConditionalTests: true,
ignoreIfStatements: false,
ignoreMixedLogicalExpressions: false,
ignorePrimitives: {
bigint: false,
boolean: false,
number: false,
string: false,
},
ignoreTernaryTests: false,
},
];

¥Options

ignoreTernaryTests

是否忽略任何可以通过使用空值合并运算符简化的三元表达式。 Default: false.

带有 { ignoreTernaryTests: false } 的此规则的代码示例:

¥Examples of code for this rule with { ignoreTernaryTests: false }:

declare const a: any;
a !== undefined && a !== null ? a : 'a string';
a === undefined || a === null ? 'a string' : a;
a == undefined ? 'a string' : a;
a == null ? 'a string' : a;

declare const b: string | undefined;
b !== undefined ? b : 'a string';
b === undefined ? 'a string' : b;
b ? b : 'a string';
!b ? 'a string' : b;

declare const c: string | null;
c !== null ? c : 'a string';
c === null ? 'a string' : c;
c ? c : 'a string';
!c ? 'a string' : c;
Open in Playground

ignoreIfStatements

是否忽略可以通过使用空值合并运算符简化的任何 if 语句。 Default: false.

带有 { ignoreIfStatements: false } 的此规则的代码示例:

¥Examples of code for this rule with { ignoreIfStatements: false }:

declare let foo: { a: string } | null;
declare function makeFoo(): { a: string };

function lazyInitializeFoo1() {
if (!foo) {
foo = makeFoo();
}
}

function lazyInitializeFoo2() {
if (!foo) foo = makeFoo();
}
Open in Playground

ignoreConditionalTests

是否忽略位于条件测试中的案例。 Default: true.

通常,条件测试中的表达式会故意使用逻辑或运算符的虚假失败行为,这意味着将运算符固定为空合并运算符可能会导致错误。

¥Generally expressions within conditional tests intentionally use the falsy fallthrough behavior of the logical or operator, meaning that fixing the operator to the nullish coalesce operator could cause bugs.

如果你希望强制执行更严格的条件测试,则应考虑使用 strict-boolean-expressions 规则。

¥If you're looking to enforce stricter conditional tests, you should consider using the strict-boolean-expressions rule.

带有 { ignoreConditionalTests: false } 的此规则的代码示例:

¥Examples of code for this rule with { ignoreConditionalTests: false }:

declare let a: string | null;
declare const b: string | null;

if (a || b) {
}
if ((a ||= b)) {
}
while (a || b) {}
while ((a ||= b)) {}
do {} while (a || b);
for (let i = 0; a || b; i += 1) {}
a || b ? true : false;
Open in Playground

ignoreMixedLogicalExpressions

是否忽略任何属于混合逻辑表达式(带有 &&)的逻辑或表达式。 Default: false.

通常,混合逻辑表达式中的表达式会故意使用逻辑或运算符的虚假失败行为,这意味着将运算符固定为空合并运算符可能会导致错误。

¥Generally expressions within mixed logical expressions intentionally use the falsy fallthrough behavior of the logical or operator, meaning that fixing the operator to the nullish coalesce operator could cause bugs.

如果你希望强制执行更严格的条件测试,则应考虑使用 strict-boolean-expressions 规则。

¥If you're looking to enforce stricter conditional tests, you should consider using the strict-boolean-expressions rule.

带有 { ignoreMixedLogicalExpressions: false } 的此规则的代码示例:

¥Examples of code for this rule with { ignoreMixedLogicalExpressions: false }:

declare let a: string | null;
declare const b: string | null;
declare const c: string | null;
declare const d: string | null;

a || (b && c);
a ||= b && c;
(a && b) || c || d;
a || (b && c) || d;
a || (b && c && d);
Open in Playground

注意:此特定情况的错误将作为建议渲染(见下文),而不是修复。这是因为在混合逻辑表达式中自动将 || 转换为 ?? 并不总是安全的,因为我们无法判断运算符的预期优先级。请注意,根据设计,?? 在与同一表达式中的 &&|| 一起使用时需要括号。

¥NOTE: Errors for this specific case will be presented as suggestions (see below), instead of fixes. This is because it is not always safe to automatically convert || to ?? within a mixed logical expression, as we cannot tell the intended precedence of the operator. Note that by design, ?? requires parentheses when used with && or || in the same expression.

ignorePrimitives

是否忽略所有(true)或部分(具有属性的对象)原始类型。 Default: {"bigint":false,"boolean":false,"number":false,"string":false}.

如果你想忽略包含某些可能为假的基元类型的操作数的表达式,那么你可以传递一个包含每个基元的布尔值的对象:

¥If you would like to ignore expressions containing operands of certain primitive types that can be falsy then you may pass an object containing a boolean value for each primitive:

  • string: true,忽略 nullundefinedstring 的联合(默认值:false)。

    ¥string: true, ignores null or undefined unions with string (default: false).

  • number: true,忽略 nullundefinednumber 的联合(默认值:false)。

    ¥number: true, ignores null or undefined unions with number (default: false).

  • bigint: true,忽略 nullundefinedbigint 的联合(默认值:false)。

    ¥bigint: true, ignores null or undefined unions with bigint (default: false).

  • boolean: true,忽略 nullundefinedboolean 的联合(默认值:false)。

    ¥boolean: true, ignores null or undefined unions with boolean (default: false).

带有 { ignorePrimitives: { string: false } } 的此规则的代码示例:

¥Examples of code for this rule with { ignorePrimitives: { string: false } }:

declare const foo: string | undefined;

foo || 'a string';
Open in Playground

此外,如果你想忽略所有原始类型,可以设置 ignorePrimitives: true。它等同于 ignorePrimitives: { string: true, number: true, bigint: true, boolean: true }

¥Also, if you would like to ignore all primitives types, you can set ignorePrimitives: true. It is equivalent to ignorePrimitives: { string: true, number: true, bigint: true, boolean: true }.

ignoreBooleanCoercion

是否忽略 Boolean 构造函数的参数 Default: false.

带有 { ignoreBooleanCoercion: false } 的此规则的代码示例:

¥Examples of code for this rule with { ignoreBooleanCoercion: false }:

declare const a: string | true | undefined;
declare const b: string | boolean | undefined;

const x = Boolean(a || b);
Open in Playground

allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing

已弃用

此选项将在下一个主要版本的 typescript-eslint 中删除。

¥This option will be removed in the next major version of typescript-eslint.

除非将其设置为 true,否则规则将在每个 tsconfig.json 没有将 strictNullChecks 编译器选项(或 strict)设置为 true 的文件上出错。 Default: false.

如果没有 strictNullChecks,TypeScript 基本上会从类型中删除 undefinednull。这意味着当此规则检查变量的类型时,它将无法判断变量可能是 null 还是 undefined,这实际上使此规则毫无用处。

¥Without strictNullChecks, TypeScript essentially erases undefined and null from the types. This means when this rule inspects the types from a variable, it will not be able to tell that the variable might be null or undefined, which essentially makes this rule useless.

你应该使用 strictNullChecks 来确保代码库中的完全类型安全。

¥You should be using strictNullChecks to ensure complete type-safety in your codebase.

如果由于某种原因你无法打开 strictNullChecks,但仍想使用此规则 - 你可以使用此选项来允许它 - 但要知道,如果关闭编译器选项,此规则的行为是未定义的。如果你使用此选项,我们将不接受错误报告。

¥If for some reason you cannot turn on strictNullChecks, but still want to use this rule - you can use this option to allow it - but know that the behavior of this rule is undefined with the compiler option turned off. We will not accept bug reports if you are using this option.

何时不使用它

¥When Not To Use It

如果你不使用 TypeScript 3.7(或更高版本),那么你将无法使用此规则,因为不支持该运算符。

¥If you are not using TypeScript 3.7 (or greater), then you will not be able to use this rule, as the operator is not supported.

进一步阅读

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

资源