Domů O mně Služby Portfolio Učím Blog Kontakt
← Zpět na učím

05.8 Nullish coalescing

Výuka

Proč nullish coalescing?

Nullish coalescing operátor (??) vrací pravou hodnotu, pokud levá je null nebo undefined. Na rozdíl od || nenahrazuje falsy hodnoty jako 0, '', false.

Proč to potřebujeme?

  • Default hodnoty - Nastav default jen pro null/undefined
  • Přesnější než || - 0, '', false jsou validní hodnoty
  • Bezpečný fallback - Vrať alternativu jen když hodnota chybí
  • Kombinace s ?. - Bezpečný přístup + default hodnota

Představ si to jako: Záložní plán. Pokud tvůj hlavní plán neexistuje (null/undefined), použiješ záložní. Ale pokud hlavní plán je "nic nedělat" (0, '', false), to je stále validní plán!

Jak to funguje?

Nullish coalescing (a ?? b):
1. Pokud a je null NEBO undefined  vrať b
2. Jinak vrať a
3. NENAHRAZUJE falsy hodnoty (0, '', false) - jen null/undefined

Klíčové koncepty

  • Nullish coalescing ?? - vrať pravou hodnotu jen pro null/undefined
  • Nullish values - null a undefined (ne ostatní falsy!)
  • ES2020 feature - od ES2020
  • Rozdíl od || - || nahrazuje všechny falsy hodnoty
  • Short-circuit - pokud levá strana není null/undefined, pravá se nevyhodnotí

JavaScript

Příklad 1: Základní nullish coalescing

const user = {
  name: 'Alice',
  age: 25
};

// Pokud vlastnost existuje - vrať ji
const userName = user.name ?? 'Anonym';
console.log(userName);
// → Alice

// Pokud vlastnost neexistuje - vrať default
const userEmail = user.email ?? 'no-email@example.com';
console.log(userEmail);
// → no-email@example.com

// Null hodnota - vrať default
const user2 = {
  name: 'Bob',
  email: null
};

const email = user2.email ?? 'default@example.com';
console.log(email);
// → default@example.com

Co se stalo?

  • a ?? b - pokud a je null nebo undefined, vrať b
  • Jinak vrať a
  • Užitečné pro default hodnoty

Příklad 2: Rozdíl mezi ?? a ||

const settings = {
  volume: 0,         // 0 je validní hodnota!
  muted: false,      // false je validní hodnota!
  theme: '',         // '' je validní hodnota!
  language: undefined
};

// S || - ŠPATNĚ!
console.log(settings.volume || 50);
// → 50 (CHYBA! 0 je falsy, ale validní hodnota)

console.log(settings.muted || true);
// → true (CHYBA! false je falsy, ale validní hodnota)

console.log(settings.theme || 'light');
// → light (CHYBA! '' je falsy, ale validní hodnota)

// S ?? - SPRÁVNĚ!
console.log(settings.volume ?? 50);
// → 0 (SPRÁVNĚ! 0 není null/undefined)

console.log(settings.muted ?? true);
// → false (SPRÁVNĚ! false není null/undefined)

console.log(settings.theme ?? 'light');
// → '' (SPRÁVNĚ! '' není null/undefined)

console.log(settings.language ?? 'cs');
// → cs (SPRÁVNĚ! undefined → použij default)

Co se stalo?

  • || nahrazuje VŠECHNY falsy (0, '', false, null, undefined, NaN)
  • ?? nahrazuje JEN null a undefined
  • Pro default hodnoty preferuj ?? - přesnější!

Příklad 3: Kombinace s optional chaining

const user = {
  name: 'Charlie',
  preferences: {
    theme: 'dark'
  }
};

// Optional chaining + nullish coalescing
const theme = user?.preferences?.theme ?? 'light';
console.log(theme);
// → dark

const user2 = {
  name: 'David'
  // preferences neexistuje
};

const theme2 = user2?.preferences?.theme ?? 'light';
console.log(theme2);
// → light

// Praktický příklad - API response
const apiResponse = {
  data: {
    user: {
      name: 'Eve',
      settings: {
        notifications: true
      }
    }
  }
};

const notifications = apiResponse?.data?.user?.settings?.notifications ?? false;
console.log(notifications);
// → true

const apiResponse2 = {};
const notifications2 = apiResponse2?.data?.user?.settings?.notifications ?? false;
console.log(notifications2);
// → false

Co se stalo?

  • ?. + ?? - kombinace pro bezpečný přístup s default hodnotou
  • obj?.prop ?? default - vrať vlastnost nebo default
  • Velmi užitečné pro API responses a neúplná data

Příklad 4: Řetězení nullish coalescing

const config = {
  userSettings: undefined,
  defaultSettings: null,
  fallbackSettings: {
    theme: 'light',
    fontSize: 14
  }
};

// Řetězení - první ne-null/undefined vyhrává
const settings = config.userSettings ?? config.defaultSettings ?? config.fallbackSettings;
console.log(settings);
// → { theme: 'light', fontSize: 14 }

// Praktický příklad - více úrovní fallbacku
function getPort() {
  return undefined;
}

const port = process.env.PORT ?? getPort() ?? 3000;
console.log(port);
// → 3000 (process.env.PORT je undefined, getPort() vrací undefined)

Co se stalo?

  • Řetězení: a ?? b ?? c - první ne-null/undefined vyhrává
  • Užitečné pro více úrovní fallbacku
  • Short-circuit - zastaví se u první validní hodnoty

Příklad 5: Nullish coalescing assignment (??=)

let config = {
  theme: 'dark'
};

// Přiřaď jen pokud vlastnost je null/undefined
config.theme ??= 'light';
console.log(config.theme);
// → dark (theme už existuje, nepřepíše se)

config.fontSize ??= 14;
console.log(config.fontSize);
// → 14 (fontSize neexistoval, přiřadil se)

// Ekvivalentní k:
config.theme = config.theme ?? 'light';
config.fontSize = config.fontSize ?? 14;

// Praktický příklad - inicializace defaults
const userSettings = {
  volume: 0  // 0 je validní!
};

userSettings.volume ??= 50;
console.log(userSettings.volume);
// → 0 (SPRÁVNĚ! 0 není null/undefined, nepřepíše se)

userSettings.theme ??= 'light';
console.log(userSettings.theme);
// → light (theme neexistoval, přiřadil se)

Co se stalo?

  • ??= - nullish coalescing assignment
  • Přiřaď hodnotu jen pokud vlastnost je null nebo undefined
  • Užitečné pro inicializaci defaults

Příklad 6: Použití s funkcemi

function greet(name) {
  const displayName = name ?? 'Guest';
  return `Hello, ${displayName}!`;
}

console.log(greet('Alice'));
// → Hello, Alice!

console.log(greet(undefined));
// → Hello, Guest!

console.log(greet(null));
// → Hello, Guest!

console.log(greet(''));
// → Hello, ! ('' není null/undefined!)

// Lepší verze - kontrola i prázdného stringu
function greet2(name) {
  const displayName = name || 'Guest';  // Použij || pro prázdný string
  return `Hello, ${displayName}!`;
}

console.log(greet2(''));
// → Hello, Guest!

// Nebo kombinace
function greet3(name) {
  const displayName = (name ?? '').trim() || 'Guest';
  return `Hello, ${displayName}!`;
}

console.log(greet3(''));
// → Hello, Guest!

console.log(greet3('  '));
// → Hello, Guest! (whitespace oříznut)

console.log(greet3('Alice'));
// → Hello, Alice!

Co se stalo?

  • ?? v parametrech - default hodnota pro null/undefined
  • Pro prázdné stringy použij || (pokud je chceš nahradit)
  • Můžeš kombinovat ?? a || podle potřeby

TypeScript

TypeScript přidává typovou kontrolu nullish coalescing.

Stejné příklady s typy

// Základní použití s typy
const user: { name: string; email?: string } = {
  name: 'Alice'
};

const email: string = user.email ?? 'no-email@example.com';
// TypeScript inferuje: string

// S union types
type Config = {
  port: number | null | undefined;
  host: string | null;
};

const config: Config = {
  port: null,
  host: null
};

const port: number = config.port ?? 3000;
const host: string = config.host ?? 'localhost';

// Type narrowing
function getPort(config: Config): number {
  return config.port ?? 3000;  // ✅ TypeScript ví, že výsledek je number
}

// Nullish coalescing s optional properties
interface User {
  name: string;
  age?: number;
  email?: string | null;
}

const user: User = {
  name: 'Bob'
};

const age: number = user.age ?? 0;
const email: string = user.email ?? 'no-email';

// Generické funkce
function getOrDefault<T>(value: T | null | undefined, defaultValue: T): T {
  return value ?? defaultValue;
}

const result1: number = getOrDefault(null, 42);  // → 42
const result2: string = getOrDefault('hello', 'default');  // → hello
const result3: number = getOrDefault(0, 42);  // → 0 (0 není null!)

// S strictNullChecks
const maybeString: string | null = Math.random() > 0.5 ? 'value' : null;
const definiteString: string = maybeString ?? 'default';
// TypeScript ví, že definiteString je vždy string

TypeScript přidává:

  • Typovou kontrolu - TypeScript ví, že výsledek nikdy není null/undefined
  • Type narrowing - lepší inference typů
  • Union types - T | null | undefined
  • Prevenci chyb - upozorní na možné problémy

Rozdíl JS vs TS

JavaScript:

  • ?? funguje bez typové kontroly
  • Musíš ručně kontrolovat typy
  • Flexibilnější, ale nebezpečnější

TypeScript:

  • TypeScript ví, že výsledek nikdy není null/undefined
  • Lepší type narrowing
  • Bezpečnější, prevence chyb
// JavaScript - musíš ručně kontrolovat
const value = config.port ?? 3000;
// value může být number nebo cokoliv jiného

// TypeScript - type narrowing
interface Config {
  port: number | null;
}

const config: Config = { port: null };
const value: number = config.port ?? 3000;
// TypeScript ví, že value je VŽDY number

Tip

💡 Preferuj ?? místo || pro default hodnoty:

// ❌ || nahrazuje 0, '', false (problém!)
const volume = settings.volume || 50;  // 0 → 50 (CHYBA!)

// ✅ ?? nahrazuje jen null/undefined
const volume = settings.volume ?? 50;  // 0 → 0 (SPRÁVNĚ!)

💡 Kombinuj ?. s ?? pro bezpečný přístup:

// ✅ Bezpečný přístup + default hodnota
const city = user?.address?.city ?? 'Unknown';

// Místo
const city = (user && user.address && user.address.city) || 'Unknown';

💡 Používej ??= pro inicializaci defaults:

// ✅ Inicializuj jen pokud neexistuje
config.theme ??= 'light';
config.fontSize ??= 14;

// Místo
if (config.theme === null || config.theme === undefined) {
  config.theme = 'light';
}

Kvíz

Co vypíše tento kód?

const settings = {
  volume: 0,
  muted: false
};

console.log(settings.volume ?? 50);
console.log(settings.volume || 50);

- || nahrazuje falsy hodnoty, včetně 0

- ?? nenahrazuje 0, jen null/undefined

- - settings.volume ?? 50: - settings.volume = 0 - 0 NENÍ null ani undefined - ?? vrací 0 (levou hodnotu)

  • settings.volume || 50:
    • settings.volume = 0
    • 0 je falsy hodnota
    • || vrací 50 (pravou hodnotu)

- Obrácené hodnoty

Důležité: ?? nahrazuje JEN null a undefined, zatímco || nahrazuje VŠECHNY falsy hodnoty (0, '', false, null, undefined, NaN)!

Důležité: ?? nahrazuje JEN null a undefined, zatímco || nahrazuje VŠECHNY falsy hodnoty (0, '', false, null, undefined, NaN)!

🎯 Závěrečný projekt

Po dokončení všech 8 dílů vytvoříte jednoduchou Todо aplikaci v čistém JavaScriptu. Naučíte se, jak aplikovat vše, co jste se naučili, na reálný projekt.

Zobrazit podrobnosti projektu →

Připraveni začít?

Zaregistrujte se a získejte přístup ke všem dílům tohoto seriálu

Kontaktujte mě

Informace o seriálu

Obtížnost

Délka

Cca 480 minut

Počet videí

8 videí + projekty

Certifikát

Po dokončení obdržíte certifikát


Lekce v této sekci


Struktura lekcí (souborový strom)

06. Typescript specifika
  • v přípravě
08. Moduly tridy
  • v přípravě
09. React zaklady
  • v přípravě
10. React hooks
  • v přípravě
12. Nextjs server
  • v přípravě
13. Databaze auth
  • v přípravě
14. Nextjs pokrocile
  • v přípravě