@typescript-eslint/strict-boolean-expressions

Disallow nullable numbers, strings, and booleans, any, and always-true values in conditions

has suggestionsneeds types

Also called typescript-eslint/strict-boolean-expressions, typescript/strict-boolean-expressions

if (count) on a number | undefined is false for undefined, and also for 0 and NaN. if (name) on an optional string is also false for "". Code that means "was it given?" then skips a valid value.

This rule checks the conditions of if, while, do, for, and ? :, the operand of !, the left side of && and ||, and the return value of callbacks passed to filter, find, some, every, and similar array methods.

By default a condition can be a boolean, a string, a number, or an object that can be null or undefined. These are reported:

  • a boolean, string, number, or enum that can also be null or undefined
  • any and unknown
  • a mix such as string | number
  • an object that's never nullish, which is always true
  • a value that's always nullish, which is always false

This rule needs strictNullChecks (or strict) in your tsconfig.json.

Configure#

Off by default. This rule needs types, so turning it on makes bun lint type check your code first.

bunfig.toml
[lint.rules]
"@typescript-eslint/strict-boolean-expressions" = "error" # or "warn"

Every option, set to its default:

bunfig.toml
[lint.rules]
"@typescript-eslint/strict-boolean-expressions" = ["error", {
  allowString = true,
  allowNumber = true,
  allowNullableObject = true,
  allowNullableBoolean = false,
  allowNullableString = false,
  allowNullableNumber = false,
  allowNullableEnum = false,
  allowAny = false,
  allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing = false,
}]

Examples#

example.ts3 problems
function render(width?: number, title?: string, items: string[] = []) {
  if (width) {
    resize(width); // skipped for 0
  }
  const heading = title || "Untitled"; // replaces ""
  if (items) {
    draw(items); // always runs, even for []
  }
}

declare function resize(width: number): void;
declare function draw(items: string[]): void;
example.tsNo problems
function render(width?: number, title?: string, items: string[] = []) {
  if (width !== undefined) {
    resize(width);
  }
  const heading = title ?? "Untitled";
  if (items.length > 0) {
    draw(items);
  }
}

declare function resize(width: number): void;
declare function draw(items: string[]): void;

Array method callbacks, unknown, and mixed types are reported too:

example.ts3 problems
function pick(sizes: (number | undefined)[], raw: unknown, id: string | number) {
  const known = sizes.filter(size => size); // drops 0 too
  if (raw) console.log(raw);
  if (id) console.log(id);
}

A nullable object has only one falsy case, so it's allowed:

example.tsNo problems
function nameOf(user?: { name: string }) {
  return user ? user.name : "guest";
}

Options#

OptionDefaultWhat it does
allowStringtrueAllow string.
allowNumbertrueAllow number and bigint.
allowNullableObjecttrueAllow an object, function, or symbol that can be nullish.
allowNullableBooleanfalseAllow boolean | null | undefined.
allowNullableStringfalseAllow string | null | undefined.
allowNullableNumberfalseAllow number | null | undefined.
allowNullableEnumfalseAllow an enum that can be nullish.
allowAnyfalseAllow any and unknown.
allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoingfalseDon't report a project that has strictNullChecks off. Without it TypeScript hides null and undefined from types, so the rule misses most cases.

Turn off allowString and allowNumber to accept only real booleans and nullable objects. These are then reported:

example.tswith { "allowString": false, "allowNumber": false }2 problems
function summary(items: string[], query: string) {
  if (items.length) {
    console.log(items.length);
  }
  return query ? `Results for ${query}` : "All";
}

An optional flag is a common case to allow. Use allowNullableBoolean for that:

example.tswith { "allowNullableBoolean": true }No problems
function build(options: { minify?: boolean }) {
  if (options.minify) {
    console.log("minifying");
  }
}

When not to use it#

In a codebase that relies on truthiness checks, this rule reports a lot of code that works. Start with the allowNullable options on, or leave it off.