AceDevHub
Modern PatternsFree

Optional Chaining and Nullish Coalescing

Safely access nested data with ?. and default values with ?? — without the bugs that && and || defaults introduce.

IntermediateFreeModern ES

API responses and form state are deeply nested and often incomplete. Before ES2020, developers chained && checks or try/catch blocks to avoid "Cannot read property of undefined." Optional chaining (?.) and nullish coalescing (??) are now the standard — but they solve different problems than || and &&, and mixing them incorrectly still ships bugs to production.

Optional chaining — short-circuit on null/undefined

Optional chaining stops evaluation when it hits null or undefined and returns undefined instead of throwing. It works for property access (obj?.prop), bracket access (obj?.[key]), and method calls (obj?.method?.()). It does not catch missing DOM nodes in invalid HTML — it only guards nullish roots.

optional-chaining.js
Loading editor…
Outputconsole
Sangam
undefined
undefined
ok

Nullish coalescing — default only for null/undefined

?? returns the right-hand side only when the left is null or undefined — not when it is 0, "", or false. That fixes the classic || bug: const page = query.page || 1 turns page 0 into 1. Use ?? when 0 and empty string are valid values (pagination, user input, numeric counters).

nullish-coalescing.js
Loading editor…
Outputconsole
3
0
default

true
false

Combining ?. and ?? in API mappers

Real backend JSON often omits keys entirely. A mapper layer normalizes shape for the UI: read with ?., default with ??, validate types before render. This pattern appears in every AceDevHub page that consumes Fastify API envelopes.

api-mapper.js
Loading editor…
Outputconsole
{ id: 7, displayName: 'dev@acedevhub.com', plan: 'free', avatarUrl: null }
OperatorLeft is 0 or ""Left is null/undefined
a || bUses bUses b
a ?? bUses aUses b
a?.bAccesses bReturns undefined

Optional chaining and nullish coalescing reduce defensive if ladders when mapping API JSON, but they do not validate shape at runtime. TypeScript and Zod still matter for external data. Use ?. ?? together: ?. for safe navigation, ?? for defaults that respect 0 and empty string.

Combining with logical operators

Mixing ?. with && and || requires parentheses — operator precedence still applies. (user?.flags?.beta) ?? false is clearer than user?.flags?.beta || false when false is a valid flag value. When in doubt, assign to a named const and branch explicitly — readability beats one-liner density.


  1. 1?. stops at null/undefined — returns undefined, no throw
  2. 2?? defaults only null/undefined — keeps 0, "", false
  3. 3Combine in API mappers for safe nested reads
  4. 4Avoid || for numeric and string defaults when falsy is valid
  5. 5Next lesson: fetch and JSON end-to-end