0Pricing
TypeScript Academy · Lesson

Combining ?. and ??

Pair optional chaining with sensible default values.

Combining ?. and ?? is a free TypeScript Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the TypeScript Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

A Perfect Pairing

Optional chaining and nullish coalescing are designed to work together. The pattern obj?.value ?? fallback safely reads a nested value and supplies a default if it's missing. It's one of the most useful idioms in modern TypeScript.

type User = { profile?: { name?: string } };
const u: User = {};
const name = u.profile?.name ?? 'Anonymous';
console.log(name);

How the Pattern Works

First ?. evaluates the chain, yielding the value or undefined. Then ?? checks that result: if it's nullish, the fallback is used. Two operators, one clean expression.

type Cfg = { server?: { port?: number } };
const cfg: Cfg = { server: {} };
const port = cfg.server?.port ?? 8080;
console.log(port);

The Type of the Result

The chain produces T | undefined; the ?? removes undefined and unions the fallback's type. With a matching fallback, the final type is just T — no undefined left to handle.

type Cfg = { timeout?: number };
const cfg: Cfg = {};
const timeout: number = cfg.timeout ?? 30;
console.log(timeout + 5); // number, safe arithmetic

Preserving Valid Falsy Values

Because ?? only triggers on nullish, a legitimate 0 retrieved through the chain is preserved. The fallback applies only when the property is genuinely missing.

type Audio = { settings?: { volume?: number } };
const a: Audio = { settings: { volume: 0 } };
console.log(a.settings?.volume ?? 50); // 0, not 50

Deep Config Access

For deeply nested configuration, chain multiple ?. steps and finish with a single ??. Any missing link cleanly falls back to the default.

type Cfg = { db?: { pool?: { max?: number } } };
const cfg: Cfg = { db: {} };
const maxPool = cfg.db?.pool?.max ?? 10;
console.log(maxPool);

API Response Defaults

API responses often omit optional fields. The combined pattern reads them defensively and substitutes sensible defaults, keeping downstream code simple and crash-free.

type Res = { data?: { items?: string[] } };
const res: Res = { data: {} };
const items = res.data?.items ?? [];
console.log('Item count:', items.length);

Combining With Method Results

You can chain off function or method calls and default their results. If the call returns nullish, the fallback steps in.

type Store = { find?: () => string | undefined };
const store: Store = { find: () => undefined };
const result = store.find?.() ?? 'default';
console.log(result);

Avoiding Verbose Guards

Before these operators you'd write multi-line null checks. The combined idiom replaces a whole block with a single expression, improving readability without losing safety.

type User = { name?: string };
const u: User = {};
// Old: let n; if (u && u.name) n = u.name; else n = 'Guest';
const n = u?.name ?? 'Guest';
console.log(n);

Fallback to Another Lookup

The fallback after ?? can itself be another chained lookup, letting you try a secondary source before a final literal default.

type Prefs = { theme?: string };
const userPrefs: Prefs = {};
const sitePrefs: Prefs = { theme: 'light' };
const theme = userPrefs?.theme ?? sitePrefs?.theme ?? 'dark';
console.log(theme);

Combining With Element Access

The pattern works with array element access too: read an element through ?.[i] and default it with ??.

type Data = { tags?: string[] };
const d: Data = { tags: [] };
const first = d.tags?.[0] ?? 'none';
console.log(first);

A Real-World Settings Reader

Putting it together: a settings reader that safely descends through optional layers and guarantees a usable value. This is production TypeScript you'll write often.

type Settings = { ui?: { lang?: string } };
function getLang(s: Settings): string {
  return s.ui?.lang ?? 'en';
}
console.log(getLang({ ui: { lang: 'tr' } }), getLang({}));

Quick Check

Test your understanding of combining ?. and ??.

Recap: Combining ?. and ??

You learned the idiom obj?.value ?? fallback:

  • ?. safely descends, yielding the value or undefined.
  • ?? supplies a default only when the result is nullish.
  • The final type drops undefined, often becoming a clean T.
  • Valid falsy values like 0 are preserved.

Next, optional calls and optional element access.

type Cfg = { limit?: number };
const c: Cfg = {};
const limit = c?.limit ?? 100;
console.log(limit);

Frequently asked questions

Is the “Combining ?. and ??” lesson free?

Yes — the full text of “Combining ?. and ??” is free to read here on the web, and the TypeScript Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the TypeScript Academy course, upgrade to CoddyKit PRO.

What will I learn in “Combining ?. and ??”?

Pair optional chaining with sensible default values. You practise TypeScript Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start TypeScript Academy?

No prior experience is required. TypeScript Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Combining ?. and ??” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this TypeScript Academy lesson?

Yes. Every TypeScript Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Optional Chaining with ?.
  2. Nullish Coalescing with ??
  3. Combining ?. and ??
  4. Optional Calls and Element Access
← Back to TypeScript Academy