no-unnecessary-condition
Disallow conditionals where the type is always truthy or always falsy.
在 ESLint 配置 中扩展"plugin:@typescript-eslint/strict-type-checked"
可启用此规则。
此规则报告的一些问题可通过 --fix
ESLint 命令行选项自动修复。
该规则需要 类型信息 才能运行,但这会带来性能方面的权衡。
任何用作条件的表达式都必须能够评估为 真或假才能被视为 "necessary"。相反,任何始终计算结果为真或总是计算结果为假的表达式(由表达式的类型决定)都被认为是不必要的,并将被此规则标记。
¥Any expression being used as a condition must be able to evaluate as truthy or falsy in order to be considered "necessary". Conversely, any expression that always evaluates to truthy or always evaluates to falsy, as determined by the type of the expression, is considered unnecessary and will be flagged by this rule.
检查以下表达式:
¥The following expressions are checked:
-
&&
、||
和?:
(三元)运算符的参数¥Arguments to the
&&
,||
and?:
(ternary) operators -
if
、for
、while
和do-while
语句的条件¥Conditions for
if
,for
,while
, anddo-while
statements -
switch
中的case
语句¥
case
s inswitch
statements -
可选链表达式的基值
¥Base values of optional chain expressions
- Flat Config
- Legacy Config
export default tseslint.config({
rules: {
"@typescript-eslint/no-unnecessary-condition": "error"
}
});
module.exports = {
"rules": {
"@typescript-eslint/no-unnecessary-condition": "error"
}
};
在线运行试试这个规则 ↗
示例
¥Examples
- ❌ Incorrect
- ✅ Correct
function head<T>(items: T[]) {
// items can never be nullable, so this is unnecessary
if (items) {
return items[0].toUpperCase();
}
}
function foo(arg: 'bar' | 'baz') {
// arg is never nullable or empty string, so this is unnecessary
if (arg) {
}
}
function bar<T>(arg: string) {
// arg can never be nullish, so ?. is unnecessary
return arg?.length;
}
// Checks array predicate return types, where possible
[
[1, 2],
[3, 4],
].filter(t => t); // number[] is always truthy
Open in Playgroundfunction head<T>(items: T[]) {
// Necessary, since items.length might be 0
if (items.length) {
return items[0].toUpperCase();
}
}
function foo(arg: string) {
// Necessary, since arg might be ''.
if (arg) {
}
}
function bar(arg?: string | null) {
// Necessary, since arg might be nullish
return arg?.length;
}
[0, 1, 2, 3].filter(t => t); // number can be truthy or falsy
Open in Playground选项
该规则接受以下选项:
type Options = [
{
/** Whether to ignore constant loop conditions, such as `while (true)`. */
allowConstantLoopConditions?:
| 'always'
| 'never'
| 'only-allowed-literals'
/** Whether to ignore constant loop conditions, such as `while (true)`. */
| boolean;
/** Whether to not error when running with a tsconfig that has strictNullChecks turned. */
allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing?: boolean;
/** Whether to check the asserted argument of a type predicate function for unnecessary conditions */
checkTypePredicates?: boolean;
},
];
const defaultOptions: Options = [
{
allowConstantLoopConditions: 'never',
allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing: false,
checkTypePredicates: false,
},
];
¥Options
allowConstantLoopConditions
Whether to ignore constant loop conditions, such as while (true)
. Default: "never"
.
'never'
禁止循环中的常量条件。与 false
相同。
¥Disallow constant conditions in loops. Same as false
.
{ allowConstantLoopConditions: 'never' }
的错误代码示例:
¥Example of incorrect code for { allowConstantLoopConditions: 'never' }
:
while (true) {
// ...
}
for (; true; ) {
// ...
}
do {
// ...
} while (true);
Open in Playground'always'
允许循环中的常量条件。与 true
相同。
¥Allow constant conditions in loops. Same as true
.
{ allowConstantLoopConditions: 'always' }
的正确代码示例:
¥Example of correct code for { allowConstantLoopConditions: 'always' }
:
while (true) {
// ...
}
for (; true; ) {
// ...
}
do {
// ...
} while (true);
Open in Playground'only-allowed-literals'
允许在 while
循环条件中使用惯用的常量文字条件。
¥Permit idiomatic constant literal conditions in while
loop conditions.
具体来说,尽管 true
、false
、0
和 1
始终为真或假,但它们都是允许的,因为这些是常见模式,不太可能代表开发者错误。
¥Specifically, true
, false
, 0
, and 1
are allowed despite always being truthy or falsy, as these are common patterns and are not likely to represent developer errors.
{ allowConstantLoopConditions: 'only-allowed-literals' }
的正确代码示例:
¥Example of correct code for { allowConstantLoopConditions: 'only-allowed-literals' }
:
while (true) {
// ...
}
Open in Playground{ allowConstantLoopConditions: 'only-allowed-literals' }
的错误代码示例:
¥Example of incorrect code for { allowConstantLoopConditions: 'only-allowed-literals' }
:
// `alwaysTrue` has the type of `true` (which isn't allowed)
// as only the literal value of `true` is allowed.
declare const alwaysTrue: true;
while (alwaysTrue) {
// ...
}
// not even a variable that references the value of `true` is allowed, only
// the literal value of `true` used directly.
const thisIsTrue = true;
while (thisIsTrue) {
// ...
}
Open in PlaygroundcheckTypePredicates
Whether to check the asserted argument of a type predicate function for unnecessary conditions Default: false
.
{ checkTypePredicates: true }
的其他不正确代码示例:
¥Example of additional incorrect code with { checkTypePredicates: true }
:
function assert(condition: unknown): asserts condition {
if (!condition) {
throw new Error('Condition is falsy');
}
}
assert(false); // Unnecessary; condition is always falsy.
const neverNull = {};
assert(neverNull); // Unnecessary; condition is always truthy.
function isString(value: unknown): value is string {
return typeof value === 'string';
}
declare const s: string;
// Unnecessary; s is always a string.
if (isString(s)) {
}
function assertIsString(value: unknown): asserts value is string {
if (!isString(value)) {
throw new Error('Value is not a string');
}
}
assertIsString(s); // Unnecessary; s is always a string.
Open in Playground此选项是否适合你的项目可能会有所不同。一些项目可能会故意使用类型谓词来确保运行时值确实与 TypeScript 的类型匹配,尤其是在测试代码中。通常,在这些情况下使用 eslint-disable 注释是有意义的,注释表明为什么应该在运行时检查条件,尽管看起来没有必要。但是,在某些情况下,完全禁用此选项可能更合适。
¥Whether this option makes sense for your project may vary. Some projects may intentionally use type predicates to ensure that runtime values do indeed match the types according to TypeScript, especially in test code. Often, it makes sense to use eslint-disable comments in these cases, with a comment indicating why the condition should be checked at runtime, despite appearing unnecessary. However, in some contexts, it may be more appropriate to keep this option disabled entirely.
allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing
Whether to not error when running with a tsconfig that has strictNullChecks turned. Default: false
.
此选项将在下一个主要版本的 typescript-eslint 中删除。
¥This option will be removed in the next major version of typescript-eslint.
如果将其设置为 false
,则规则将在 tsconfig.json
没有将 strictNullChecks
编译器选项(或 strict
)设置为 true
的每个文件上出错。
¥If this is set to false
, then the rule will error on every file whose tsconfig.json
does not have the strictNullChecks
compiler option (or strict
) set to true
.
如果没有 strictNullChecks
,TypeScript 基本上会从类型中删除 undefined
和 null
。这意味着当此规则检查变量的类型时,它将无法判断变量可能是 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.
局限性
¥Limitations
此规则纯粹是保持项目一致性的风格规则。这可能发生在几种常见情况下。
¥This rule is powered by TypeScript types, therefore, if the types do not match match the runtime behavior, the rule may report inaccurately. This can happen in several commonplace scenarios.
可能未定义的索引访问
¥Possibly-undefined indexed access
默认情况下,TypeScript 乐观地假设索引访问将始终返回一个值。这意味着像下面这样的情况将被错误地标记为不必要的条件:
¥By default, TypeScript optimistically assumes that indexed access will always return a value. This means that cases like the following will be erroneously flagged as unnecessary conditions:
const array: string[] = [];
const firstElement = array[0];
// false positive
if (firstElement != null) {
// ...
}
const record: Record<string, string> = {};
const someValue = record.someKey;
// false positive
if (someValue != null) {
// ...
}
Open in Playground为了在这些情况下获得悲观但正确的类型,你可以使用 TypeScript 的 noUncheckedIndexedAccess
编译器选项,尽管这在实际使用中通常很笨拙。另一种解决方法是使用 array.at(0)
(可能始终未定义)来指示可能超出范围的数组访问。否则,对于这些情况,禁用注释通常很有意义。
¥To get pessimistic, but correct, types for these cases, you can use TypeScript's noUncheckedIndexedAccess
compiler option, though this is often unwieldy in real-world usage.
Another workaround is to use array.at(0)
(which is always possibly-undefined) to indicate array access that may be out-of-bounds.
Otherwise, a disable comment will often make sense for these kinds of cases.
函数调用中修改的值
¥Values modified within function calls
以下代码将被错误地标记为不必要的,即使在函数调用中修改了条件。
¥The following code will be erroneously flagged as unnecessary, even though the condition is modified within the function call.
let condition = false;
const f = () => {
condition = Math.random() > 0.5;
};
f();
if (condition) {
// ...
}
Open in Playground这是由于 TypeScript 类型缩小的限制而发生的。参见 microsoft/TypeScript#9998 了解详情。我们建议在这些情况下使用 类型断言,如下所示:
¥This occurs due to limitations of TypeScript's type narrowing. See microsoft/TypeScript#9998 for details. We recommend using a type assertion in these cases, like so:
let condition = false as boolean;
const f = () => {
condition = Math.random() > 0.5;
};
f();
if (condition) {
// ...
}
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.
相关
¥Related To
-
ESLint:no-constant-condition -
no-unnecessary-condition
本质上是no-constant-condition
的增强版本,但需要类型信息。¥ESLint: no-constant-condition -
no-unnecessary-condition
is essentially a stronger version ofno-constant-condition
, but requires type information. -
strict-boolean-expressions -
no-unnecessary-condition
的更有态度的版本。strict-boolean-expressions
强制执行特定的代码样式,而no-unnecessary-condition
则与正确性有关。¥strict-boolean-expressions - a more opinionated version of
no-unnecessary-condition
.strict-boolean-expressions
enforces a specific code style, whileno-unnecessary-condition
is about correctness.
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.
'## 资源'