Optional Chaining, Nullish Coalescing & Non-null

The three operators for working with maybe-missing values β€” and the sharp edge on the last one.

Three operators dominate null-handling in modern TypeScript. The first two are safe and delightful; the third is a promise you make to the compiler.

Optional chaining ?.

a?.b short-circuits to undefined the moment a is null or undefined, instead of throwing. It works on properties, calls (fn?.()), and indexes (arr?.[0]).

Nullish coalescing ??

a ?? b returns b only when a is null or undefined β€” unlike ||, it lets 0, "", and false through as real values.

const port = config.port ?? 3000; // 0 would be kept; with || it would not
const name = user?.profile?.name ?? "Guest";

Non-null assertion !

value! tells the compiler "trust me, this is not null here." It removes null/undefined from the type but does nothing at runtime. If you are wrong, you get the very crash TypeScript was trying to prevent.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • A navigation menu uses optional chaining to safely access a nested user.profile.avatar URL without nested null checks.
  • A configuration loader uses nullish coalescing to fall back to a default port when the env variable is undefined.
  • A developer uses the non-null assertion on a DOM element that is guaranteed to exist by the page template.

More examples

Optional chaining on nested object

Optional chaining (?.) short-circuits to undefined if profile is missing, and ?? provides a fallback image path.

Example Β· ts
interface User {
  profile?: {
    avatar?: string;
  };
}

function getAvatar(user: User): string {
  return user.profile?.avatar ?? '/default.png';
}

Nullish coalescing vs OR

Contrasts ?? (nullish only) with || (all falsy) to show why ?? is safer when 0 or empty string are valid values.

Example Β· ts
const port = process.env.PORT ?? 3000;   // fallback only on null/undefined
const label = process.env.LABEL || 'app'; // fallback on any falsy, including ''

console.log('port:', port);
console.log('label:', label);

Non-null assertion vs guard

Shows the ! non-null assertion alongside a null guard, highlighting that the guard is safer but ! is concise when presence is guaranteed.

Example Β· ts
// Non-null assertion β€” use sparingly
const btn = document.getElementById('submit')!;
btn.addEventListener('click', () => console.log('clicked'));

// Safer: explicit check
const btn2 = document.getElementById('submit');
if (btn2) {
  btn2.addEventListener('click', () => console.log('clicked'));
}

Discussion

  • Be the first to comment on this lesson.
Optional Chaining, Nullish Coalescing & Non-null β€” TypeScript | SoundsCode