Skip to main content

strict-boolean-expressions

Disallow certain types in boolean expressions.

🔧

Some problems reported by this rule are automatically fixable by the --fix ESLint command line option.

💡

Some problems reported by this rule are manually fixable by editor suggestions.

💭

This rule requires type information to run.

Forbids usage of non-boolean types in expressions where a boolean is expected. boolean and never types are always allowed. Additional types which are considered safe in a boolean context can be configured via options.

The following nodes are considered boolean expressions and their type is checked:

  • Argument to the logical negation operator (!arg).
  • The condition in a conditional expression (cond ? x : y).
  • Conditions for if, for, while, and do-while statements.
  • Operands of logical binary operators (lhs || rhs and lhs && rhs).
    • Right-hand side operand is ignored when it's not a descendant of another boolean expression. This is to allow usage of boolean operators for their short-circuiting behavior.
  • Asserted argument of an assertion function (assert(arg)).
eslint.config.mjs
export default tseslint.config({
rules: {
"@typescript-eslint/strict-boolean-expressions": "error"
}
});

Try this rule in the playground ↗

Examples

// nullable numbers are considered unsafe by default
declare const num: number | undefined;
if (num) {
console.log('num is defined');
}

// nullable strings are considered unsafe by default
declare const str: string | null;
if (!str) {
console.log('str is empty');
}

// nullable booleans are considered unsafe by default
function foo(bool?: boolean) {
if (bool) {
bar();
}
}

// `any`, unconstrained generics and unions of more than one primitive type are disallowed
const foo = <T>(arg: T) => (arg ? 1 : 0);

// always-truthy and always-falsy types are disallowed
let obj = {};
while (obj) {
obj = getObj();
}

// assertion functions without an `is` are boolean contexts.
declare function assert(value: unknown): asserts value;
let maybeString = Math.random() > 0.5 ? '' : undefined;
assert(maybeString);
Open in Playground

Options

This rule accepts the following options:

type Options = [
{
/** Whether to allow `any`s in a boolean context. */
allowAny?: boolean;
/** Whether to allow nullable `boolean`s in a boolean context. */
allowNullableBoolean?: boolean;
/** Whether to allow nullable `enum`s in a boolean context. */
allowNullableEnum?: boolean;
/** Whether to allow nullable `number`s in a boolean context. */
allowNullableNumber?: boolean;
/** Whether to allow nullable `object`s, `symbol`s, and functions in a boolean context. */
allowNullableObject?: boolean;
/** Whether to allow nullable `string`s in a boolean context. */
allowNullableString?: boolean;
/** Whether to allow `number`s in a boolean context. */
allowNumber?: boolean;
/** Unless this is set to `true`, the rule will error on every file whose `tsconfig.json` does _not_ have the `strictNullChecks` compiler option (or `strict`) set to `true`. */
allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing?: boolean;
/** Whether to allow `string`s in a boolean context. */
allowString?: boolean;
},
];

const defaultOptions: Options = [
{
allowAny: false,
allowNullableBoolean: false,
allowNullableEnum: false,
allowNullableNumber: false,
allowNullableObject: true,
allowNullableString: false,
allowNumber: true,
allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing: false,
allowString: true,
},
];

allowString

Whether to allow strings in a boolean context. Default: true.

This can be safe because strings have only one falsy value (""). Set this to false if you prefer the explicit str != "" or str.length > 0 style.

allowNumber

Whether to allow numbers in a boolean context. Default: true.

This can be safe because numbers have only two falsy values (0 and NaN). Set this to false if you prefer the explicit num != 0 and !Number.isNaN(num) style.

allowNullableObject

Whether to allow nullable objects, symbols, and functions in a boolean context. Default: true.

This can be safe because objects, functions, and symbols don't have falsy values. Set this to false if you prefer the explicit obj != null style.

allowNullableBoolean

Whether to allow nullable booleans in a boolean context. Default: false.

This is unsafe because nullable booleans can be either false or nullish. Set this to false if you want to enforce explicit bool ?? false or bool ?? true style. Set this to true if you don't mind implicitly treating false the same as a nullish value.

allowNullableString

Whether to allow nullable strings in a boolean context. Default: false.

This is unsafe because nullable strings can be either an empty string or nullish. Set this to true if you don't mind implicitly treating an empty string the same as a nullish value.

allowNullableNumber

Whether to allow nullable numbers in a boolean context. Default: false.

This is unsafe because nullable numbers can be either a falsy number or nullish. Set this to true if you don't mind implicitly treating zero or NaN the same as a nullish value.

allowNullableEnum

Whether to allow nullable enums in a boolean context. Default: false.

This is unsafe because nullable enums can be either a falsy number or nullish. Set this to true if you don't mind implicitly treating an enum whose value is zero the same as a nullish value.

allowAny

Whether to allow anys in a boolean context. Default: false.

This is unsafe for because any allows any values and disables many type checking checks. Set this to true at your own risk.

allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing

Unless this is set to true, the rule will error on every file whose tsconfig.json does not have the strictNullChecks compiler option (or strict) set to true. Default: false.

Deprecated

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

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.

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 a lot less useful.

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

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.

Fixes and Suggestions

This rule provides following fixes and suggestions for particular types in boolean context:

  • boolean - Always allowed - no fix needed.
  • string - (when allowString is false) - Provides following suggestions:
    • Change condition to check string's length (strstr.length > 0)
    • Change condition to check for empty string (strstr !== "")
    • Explicitly cast value to a boolean (strBoolean(str))
  • number - (when allowNumber is false):
    • For array.length - Provides autofix:
      • Change condition to check for 0 (array.lengtharray.length > 0)
    • For other number values - Provides following suggestions:
      • Change condition to check for 0 (numnum !== 0)
      • Change condition to check for NaN (num!Number.isNaN(num))
      • Explicitly cast value to a boolean (numBoolean(num))
  • object | null | undefined - (when allowNullableObject is false) - Provides autofix:
    • Change condition to check for null/undefined (maybeObjmaybeObj != null)
  • boolean | null | undefined - Provides following suggestions:
    • Explicitly treat nullish value the same as false (maybeBoolmaybeBool ?? false)
    • Change condition to check for true/false (maybeBoolmaybeBool === true)
  • string | null | undefined - Provides following suggestions:
    • Change condition to check for null/undefined (maybeStrmaybeStr != null)
    • Explicitly treat nullish value the same as an empty string (maybeStrmaybeStr ?? "")
    • Explicitly cast value to a boolean (maybeStrBoolean(maybeStr))
  • number | null | undefined - Provides following suggestions:
    • Change condition to check for null/undefined (maybeNummaybeNum != null)
    • Explicitly treat nullish value the same as 0 (maybeNummaybeNum ?? 0)
    • Explicitly cast value to a boolean (maybeNumBoolean(maybeNum))
  • any and unknown - Provides following suggestions:
    • Explicitly cast value to a boolean (valueBoolean(value))

When Not To Use It

If your project isn't likely to experience bugs from falsy non-boolean values being used in logical conditions, you can skip enabling this rule.

Otherwise, this rule can be quite strict around requiring exact comparisons in logical checks. If you prefer more succinct checks over more precise boolean logic, this rule might not be for you.


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.

Resources