@typescript-eslint/strict-boolean-expressions
Disallow nullable numbers, strings, and booleans, any, and always-true values in conditions
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 benullorundefined anyandunknown- 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.
[lint.rules]
"@typescript-eslint/strict-boolean-expressions" = "error" # or "warn"Every option, set to its default:
[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#
function render(width?: number, title?: string, items: string[] = []) {
if (widthUnexpected nullable number value in conditional. Please handle the nullish/zero/NaN cases explicitly.) {
resize(width); // skipped for 0
}
const heading = titleUnexpected nullable string value in conditional. Please handle the nullish/empty cases explicitly. || "Untitled"; // replaces ""
if (itemsUnexpected object value in conditional. The condition is always true.) {
draw(items); // always runs, even for []
}
}
declare function resize(width: number): void;
declare function draw(items: string[]): void;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:
function pick(sizes: (number | undefined)[], raw: unknown, id: string | number) {
const known = sizes.filter(size => sizeUnexpected nullable number value in array predicate return type. Please handle the nullish/zero/NaN cases explicitly.); // drops 0 too
if (rawUnexpected any value in conditional. An explicit comparison or type conversion is required.) console.log(raw);
if (idUnexpected value in conditional. A boolean expression is required.) console.log(id);
}A nullable object has only one falsy case, so it's allowed:
function nameOf(user?: { name: string }) {
return user ? user.name : "guest";
}Options#
| Option | Default | What it does |
|---|---|---|
allowString | true | Allow string. |
allowNumber | true | Allow number and bigint. |
allowNullableObject | true | Allow an object, function, or symbol that can be nullish. |
allowNullableBoolean | false | Allow boolean | null | undefined. |
allowNullableString | false | Allow string | null | undefined. |
allowNullableNumber | false | Allow number | null | undefined. |
allowNullableEnum | false | Allow an enum that can be nullish. |
allowAny | false | Allow any and unknown. |
allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing | false | Don'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:
{ "allowString": false, "allowNumber": false }2 problemsfunction summary(items: string[], query: string) {
if (items.lengthUnexpected number value in conditional. An explicit zero/NaN check is required.) {
console.log(items.length);
}
return queryUnexpected string value in conditional. An explicit empty string check is required. ? `Results for ${query}` : "All";
}An optional flag is a common case to allow. Use allowNullableBoolean for that:
{ "allowNullableBoolean": true }No problemsfunction 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.