· tips  · 5 min read

The Power of the Nullish Coalescing Operator: Beyond Default Values

Learn how the nullish coalescing operator (??) helps you avoid common pitfalls with falsy values in JavaScript. Examples, gotchas, interactions with optional chaining and logical operators, TypeScript notes, and best practices included.

Learn how the nullish coalescing operator (??) helps you avoid common pitfalls with falsy values in JavaScript. Examples, gotchas, interactions with optional chaining and logical operators, TypeScript notes, and best practices included.

Why the nullish coalescing operator matters

When you want a fallback value in JavaScript, a common pattern has been to use the logical OR operator (||):

const name = userInput || 'Guest';

That works - but it treats all falsy values the same. If userInput is '', 0, or false, you’ll get 'Guest' instead of the meaningful falsy value. The nullish coalescing operator (??) was introduced in ES2020 to address this: it only falls back when the left-hand side is null or undefined, not for other falsy values.

const name = userInput ?? 'Guest';

name will be 'Guest' only if userInput is null or undefined.

(See the MDN reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator)

The exact difference: || vs ??

  • || returns the right-hand side when the left-hand side is falsy (false, 0, '', NaN, null, undefined).
  • ?? returns the right-hand side only when the left-hand side is nullish (null or undefined).

Examples:

console.log(0 || 10); // 10
console.log(0 ?? 10); // 0

console.log('' || 'default'); // 'default'
console.log('' ?? 'default'); // ''

console.log(null || 'fallback'); // 'fallback'
console.log(null ?? 'fallback'); // 'fallback'

Note: NaN is not null or undefined, so NaN ?? 5 returns NaN.

Practical examples

  1. Preserving numerical zero
function formatCount(count) {
  // We want to show 0 instead of default
  const safeCount = count ?? 0;
  return `You have ${safeCount} items`;
}

formatCount(0); // "You have 0 items"
formatCount(null); // "You have 0 items"
formatCount(); // "You have 0 items"
  1. Allowing empty strings
function displayTitle(title) {
  const safeTitle = title ?? 'Untitled';
  // Intentionally allow '' (empty string) to be used
  console.log(safeTitle);
}

displayTitle('Hello'); // 'Hello'
displayTitle(''); // ''
displayTitle(null); // 'Untitled'
  1. With functions (short-circuiting)
const val = maybeGetValue() ?? computeExpensiveFallback();

// computeExpensiveFallback() is only called if maybeGetValue() returned null/undefined

?? short-circuits like other logical operators: the right-hand side is evaluated only if needed.

Optional chaining + nullish coalescing: a powerful combo

Optional chaining (?.) and ?? are a natural pair for safely reading nested data with fallbacks:

const username = user?.profile?.username ?? 'Guest';

This will return 'Guest' when user or profile is null/undefined, but will preserve empty strings or false if those are present.

(See MDN on optional chaining: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining)

Destructuring defaults vs ??

Default values in destructuring only apply when a property is undefined, not when it is null:

const obj = { count: null };
const { count = 10 } = obj;
console.log(count); // null (default not used)

// If you want to treat both null and undefined as missing:
const count2 = obj.count ?? 10;
console.log(count2); // 10

If you prefer a destructuring-style shorthand that treats null as missing, combine destructuring with ??:

const obj = { count: null };
const { count } = obj;
const safeCount = count ?? 10; // 10

Logical nullish assignment (??=) and friends

ES2021 introduced logical assignment operators that parallel ||= and &&=. ??= assigns only if the left-hand side is null or undefined:

let options = { retries: 0 };
options.retries ??= 3;
console.log(options.retries); // 0 (preserved)

let settings = {};
settings.retries ??= 3;
console.log(settings.retries); // 3 (assigned because undefined)

Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_nullish_assignment

Mixing with || and &&: the parentheses requirement

For safety and clarity, JavaScript disallows mixing ?? with || or && without parentheses. This is to avoid ambiguous expressions due to differences in how operators treat operands.

These are invalid syntax and will throw:

// SyntaxError:
// const x = a || b ?? c;
// const y = a && b ?? c;

Use parentheses to make your intent explicit:

const x1 = (a || b) ?? c;
const x2 = a || (b ?? c);

Think about the precedence and the meaning you want when combining these operators.

TypeScript and typing considerations

TypeScript supports ?? (added in TS 3.7). With --strictNullChecks, ?? helps reduce boilerplate when dealing with T | null | undefined types:

function greet(name: string | null | undefined) {
  const who = name ?? 'friend';
  // who is typed as string here
}

Note: TypeScript’s control-flow analysis understands ?? to narrow types in many cases, but you should still be mindful when interacting with complex union types.

Browser / runtime support

?? was added in ES2020 and is supported in modern browsers and Node versions. If you need to target older environments, transpile with Babel or TypeScript. Check compatibility here: https://caniuse.com/mdn-javascript_operators_nullish_coalescing

Common pitfalls and gotchas

  • Mistaking nullish for falsy: 0, '', false, and NaN are falsy but not nullish. Use ?? when you need to preserve these values.
  • Mixing ?? with ||/&& without parentheses causes a syntax error.
  • Using ?? where you actually want any falsy value to trigger fallback: e.g., when a missing/empty string should be replaced with a default, || may be appropriate.
  • Be explicit when expressing intent. If a field can legitimately be null and that should be replaced, ?? is correct. If a field can be 0 or false and those are meaningful, avoid ||.

Best practices

  • Use ?? when you want to treat only null and undefined as missing values.
  • Prefer explicit parentheses when combining logical operators to make precedence and intent obvious.
  • Combine ?. and ?? for safe property access with sensible fallbacks.
  • Use logical nullish assignment (??=) to initialize values without overwriting meaningful falsy data.
  • When working in teams, document intent: is an empty string a valid value or should it be replaced?

Quick reference cheat-sheet

  • Use x ?? y to get x unless x is null or undefined, otherwise y.
  • Use x || y to get x unless x is falsy (0, '', false, NaN, null, undefined).
  • Use a ??= b to assign b to a only if a is null or undefined.
  • Use ?. and ?? together to safely read deep properties with defaults.

Summary

The nullish coalescing operator (??) is a small but powerful addition to JavaScript. It helps you write clearer, less error-prone code when you want to provide fallbacks for null and undefined but preserve other falsy values like 0, '', and false. Paired with optional chaining, destructuring, and logical assignment operators, ?? reduces boilerplate and makes intent explicit.

References

Back to Blog

Related Posts

View All Posts »