← Back to list

Working with Optional Chaining and Nullish Coalescing

Avoid runtime errors in JS with optional chaining and nullish coalescing. Learn how to use them right and avoid pitfalls

Adekola Olawale · 2025-09-17 13:41 · 0 claps · 3.1 min read
#javascript #optional-chaining #nullish-coalescing #js-error #clean-code
Open on Medium ↗
Wiki topics: 🌐 · Web Development

Working with Optional Chaining and Nullish Coalescing

Solving Common Pitfalls

JavaScript is notorious for throwing TypeError: Cannot read property 'x' of undefined errors at runtime.

These errors usually occur when developers try to access nested object properties that may not exist.

To make things worse, JavaScript’s loose handling of null, undefined, and falsy values often creates edge cases that are easy to overlook.

Two modern JavaScript operators — Optional Chaining (?.) and Nullish Coalescing (??), were introduced to help mitigate these issues.

They make code safer, cleaner, and more expressive.

However, they also come with subtle pitfalls that can lead to unintended bugs if misunderstood.

Let’s break them down with real-world analogies, deep dives, and practical examples.

Optional Chaining (?.): Navigating Safely

Think of optional chaining like walking into a building with multiple doors:

  • Normally, if you try to open a door that doesn’t exist, you crash into a wall (a runtime error).
  • With optional chaining, JavaScript politely checks: “Does this door exist? If not, I’ll just stop here and give you undefined instead of throwing an error.”

Example Without Optional Chaining

const user = {
  profile: {
    name: "Kola",
    address: {
      city: "Lagos"
    }
  }
};

console.log(user.profile.address.city); // "Lagos"
console.log(user.account.bank); // ❌ TypeError: Cannot read property 'bank' of undefined

Here, account doesn’t exist. Accessing bank crashes the program.

Example With Optional Chaining

console.log(user?.profile?.address?.city); // "Lagos"
console.log(user?.account?.bank); // ✅ undefined (no error)

The code safely stops whenever it encounters null or undefined.

Nullish Coalescing (??): Distinguishing Between "Nothing" and "Something"

Imagine you are filling out a form.

If the user leaves a field blank, you want to assign a default value.

But if the user explicitly sets it to something like false or 0, you should respect their choice.

That’s where ?? comes in. It only falls back to the default when the value is null or undefined — not when it’s falsy.

Example Without Nullish Coalescing

Developers often rely on the || operator:

const input = 0;
const value = input || 10; 
console.log(value); // 10 (but user actually entered 0)

Here, 0 is falsy, so || wrongly replaces it with 10.

Example With Nullish Coalescing

const input = 0;
const value = input ?? 10; 
console.log(value); // 0 ✅ correct

Now, the default applies only if input is null or undefined.

The Real Power: Combining ?. and ??

These two operators shine when used together.

Imagine you’re fetching user data from an API. Some users may not have an address. You want to show the city if it exists, otherwise fallback to "Unknown".

const user = {
  profile: {
    name: "Amina"
    // address missing
  }
};

const city = user?.profile?.address?.city ?? "Unknown";
console.log(city); // "Unknown"const city = user?.profile?.address?.city ?? "Unknown";
console.log(city); // "Unknown"

Here’s what happens step by step:

  1. Optional chaining (?.) safely attempts to navigate through profile and address.
  2. If city doesn’t exist, the result is undefined.
  3. Nullish coalescing (??) kicks in, assigning "Unknown".

This approach prevents runtime errors and ensures meaningful defaults.

Common Pitfalls and How to Avoid Them

1. Confusing ?? with ||

console.log(false || "default"); // "default"
console.log(false ?? "default"); // false
  • Use ?? when you want to distinguish between “falsy but valid” values (0, false, "") and truly missing ones (null, undefined).

2. Overusing Optional Chaining

Optional chaining is not a free pass to avoid proper validation.

If you sprinkle ?. everywhere, you might unintentionally mask logical errors.

const config = {
  retries: 3
};

console.log(config?.retryCount ?? 5); // 5

Here, a typo (retryCount instead of retries) silently returns the default instead of alerting you to a bug.

Best practice: Use optional chaining for genuinely optional values, not for critical properties you expect to always exist.

3. Forgetting Optional Chaining Doesn’t Work on the Left-Hand Side

let obj = {};
obj?.prop = "value"; // ❌ SyntaxError

Optional chaining is only for reading, not writing.

4. Combining With Function Calls

const service = {
  fetch: () => "Data"
};

console.log(service?.fetch?.()); // "Data"
console.log(service?.getData?.()); // undefined (no error)

This safely handles potentially missing functions, which is great for dynamic APIs or plugin systems.

Practical Use Cases

  1. API Responses
const user = await fetchUser();
const email = user?.contact?.email ?? "Not Provided";
  1. Configuration Settings
const maxRetries = config?.network?.retries ?? 3;
  1. Optional Callbacks
onComplete?.();

Final Thoughts

Optional Chaining and Nullish Coalescing bring clarity and safety to modern JavaScript. They let you:

  • Navigate safely through uncertain object structures.
  • Handle defaults without mistakenly overwriting valid falsy values.
  • Write cleaner, more expressive code with fewer runtime errors.

However, treat them as tools, not crutches.

Avoid overusing them to cover sloppy design or typos.

If used wisely, they can drastically improve the robustness of your applications.


메타데이터
post_id
3ab4404256f2
slug
working-with-optional-chaining-and-nullish-coalescing-3ab4404256f2
url
https://medium.com/@Adekola_Olawale/working-with-optional-chaining-and-nullish-coalescing-3ab4404256f2
canonical_url
https://medium.com/@Adekola_Olawale/working-with-optional-chaining-and-nullish-coalescing-3ab4404256f2
author_url
https://medium.com/@Adekola_Olawale
status
ok
fetched_at
2026-07-14 19:59:56