Differences Between Falsy and Nullish Values in JavaScript

Abstract image used to represent Differences Between Falsy and Nullish Values in JS
Image by Evan Buchholz.

In Brief

A falsy value becomes false in a Boolean context; the set includes false, 0, an empty string, NaN, null and undefined. Only null and undefined are nullish. Use || when any falsy value should trigger a fallback, and ?? when valid values such as 0, false or an empty string must be preserved.

The difference between a falsy value and a nullish one tends to surface when a perfectly valid 0, false, or empty string is replaced by a default. JavaScript has more falsy values than it has nullish values, and choosing between || and ?? depends on which of those values the application is allowed to keep.


Falsy Values

In JavaScript, falsy values are those that are considered false when coerced into a Boolean context and are automatically converted to false in conditions that require a Boolean result.

Here are a few examples of falsy values:

  • false
  • 0
  • '' (an empty string)
  • null
  • undefined
  • NaN (Not a Number)

The reason it's important to understand the distinction is that falsy values can lead to unintended behaviour if not handled properly in conditionals. For example:

const divideNumbers = (a: number, b: number): number => a / b;

const printResult = (result: number) => {
  if (result) {
    console.log(`Result: ${result}`);
  } else {
    console.log('No result available.');
  }
};

printResult(divideNumbers(0, 10));  //=> No result available.

In this example, divideNumbers(0, 10) returns 0. The calculation has succeeded perfectly well, but 0 is a falsy value.

That means the if (result) condition evaluates to false, and printResult reports that no result is available even though there is a legitimate result. This is exactly where a broad truthiness check can introduce a bug: sometimes 0, an empty string, or false is meaningful application data rather than an absence of data.


Nullish Values

JavaScript has two nullish values: null and undefined. Both are falsy, but the other common falsy values — such as 0, false, '', and NaN — are not nullish.

That distinction matters because "nullish" does not mean "anything that becomes false in a Boolean context". It specifically means null or undefined.

To handle nullish values and avoid potential bugs, we can use the nullish coalescing operator (??). This operator allows us to set default values when encountering null or undefined values.

const printName = (name: string | null | undefined) => {
  const defaultName = 'Anonymous';
  const finalName = name ?? defaultName;
  console.log(`Hello, ${finalName}!`);
};

printName(null);  //=> Hello, Anonymous!
printName('John');  //=> Hello, John!

In this example, the printName function uses the nullish coalescing operator to set a default name of Anonymous when the provided name is null or undefined.


The Difference in Practice

The distinction between falsy and nullish values becomes crucial when handling default values or performing conditional checks.

Consider the following example:

const fetchUserData = (user: any) => {
  const username = user.username || 'DefaultUser';
  const email = user.email ?? 'default@example.com';
  console.log(`Username: ${username}, Email: ${email}`);
};

const user1 = { username: '', email: '' };
const user2 = { username: null, email: null };
const user3 = { username: 'Sophie', email: 'sophie@example.com' };

fetchUserData(user1);  //=> Username: DefaultUser, Email: [empty string]
fetchUserData(user2);  //=> Username: DefaultUser, Email: default@example.com
fetchUserData(user3);  //=> Username: Sophie, Email: sophie@example.com

Here, we use the logical OR (||) to set default values for username and the nullish coalescing operator (??) to set default values for email.

The difference is easiest to see with user1. Its empty username is replaced by DefaultUser because '' is falsy, so the || expression falls back. Its empty email, however, is preserved because '' is not nullish, so the ?? expression does not fall back.

With user2, both expressions use their defaults because null is both falsy and nullish. With user3, neither fallback is needed because both properties already contain values.


Choosing Between || and ??

When these operators are being used to provide defaults, the useful question is not really "which one is safer?" It is: what does a missing value mean in this particular piece of code?

Consider three perfectly legitimate values:

const quantity = 0;
const enabled = false;
const label = '';

quantity || 10;  //=> 10
quantity ?? 10;  //=> 0

enabled || true;  //=> true
enabled ?? true;  //=> false

label || 'Untitled';  //=> Untitled
label ?? 'Untitled';  //=> ''

|| uses the fallback whenever the value on the left is falsy. ?? uses it only when the value is null or undefined.

Use || when 0, false, an empty string, and other falsy values should genuinely count as absent. Use ?? when those values are valid and only a nullish value should trigger the default.

That distinction here is small in syntax and yet significant in behaviour.


Wrapping‑up

Use || when every falsy value should trigger the fallback. Use ?? when 0, an empty string, or false is valid data and only null or undefined means "missing". That distinction is small in syntax and significant in configuration, form, and API code.


Have a complex web platform issue?

Tell me what is blocked, what has changed, and what needs to be true after the fix. I'll come back with a practical next step.