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

05.7 Optional chaining

Výuka

Proč optional chaining?

Optional chaining (?.) je moderní operátor pro bezpečný přístup k vnořeným vlastnostem. Místo ručního ověřování existence můžeš použít ?. a pokud vlastnost neexistuje, vrátí undefined místo chyby.

Proč to potřebujeme?

  • Prevence chyb - Žádné "Cannot read property 'x' of undefined"
  • Kratší kód - Místo několika if podmínek použiješ ?.
  • Bezpečný přístup - K vnořeným vlastnostem bez obav
  • Čitelnější kód - Jasně vidíš, co může být undefined

Představ si to jako: Bezpečnostní pojistka na dveřích. Místo "otevři dveře → otevři vnitřní dveře → vezmi klíče" (a pad nout pokud některé dveře neexistují), říkáš "zkus otevřít dveře?. → zkus otevřít vnitřní dveře?. → vezmi klíče?." - pokud cokoliv chybí, bezpečně vrátíš "nic".

Jak to funguje?

Optional chaining (?.)
1. obj?.prop - pokud obj je null/undefined  vrať undefined
2. obj?.[expr] - bezpečný bracket přístup
3. func?.() - pokud func je null/undefined  vrať undefined
4. Zastav vyhodnocení hned, jak narazíš na null/undefined

Klíčové koncepty

  • Optional chaining ?. - bezpečný přístup k vlastnostem
  • Short-circuit - zastaví se při null/undefined
  • ES2020 feature - od ES2020 (relativně nové)
  • Funkce: obj?.prop, obj?.[expr], func?.()
  • Vrací undefined - pokud vlastnost neexistuje

JavaScript

Příklad 1: Základní optional chaining

const user = {
  name: 'Alice',
  address: {
    city: 'Praha',
    zip: '11000'
  }
};

// Klasický způsob - musíš ověřit existenci
if (user && user.address && user.address.city) {
  console.log(user.address.city);
}
// → Praha

// S optional chaining - kratší a čitelnější
console.log(user?.address?.city);
// → Praha

// Pokud vlastnost neexistuje - žádná chyba
const user2 = {
  name: 'Bob'
  // address neexistuje
};

console.log(user2?.address?.city);
// → undefined (ne Error!)

// Bez optional chaining - chyba!
// console.log(user2.address.city);
// → TypeError: Cannot read property 'city' of undefined

Co se stalo?

  • ?. operátor - pokud vlastnost je null nebo undefined, vrať undefined
  • Short-circuit - zastaví se hned, jak narazí na null/undefined
  • Žádná chyba - bezpečně vrací undefined

Příklad 2: Optional chaining s funkcemi

const user = {
  name: 'Charlie',
  greet() {
    return `Hi, I'm ${this.name}`;
  }
};

// Volání metody, která existuje
console.log(user.greet?.());
// → Hi, I'm Charlie

// Volání metody, která neexistuje
const user2 = {
  name: 'David'
  // greet neexistuje
};

console.log(user2.greet?.());
// → undefined (ne Error!)

// Bez optional chaining - chyba!
// console.log(user2.greet());
// → TypeError: user2.greet is not a function

// Praktické použití - callback
const config = {
  onSuccess: () => console.log('Success!')
};

config.onSuccess?.();  // → Success!
config.onError?.();    // → undefined (onError neexistuje)

Co se stalo?

  • func?.() - pokud funkce neexistuje, vrať undefined
  • Bezpečné volání - žádná chyba pokud metoda chybí
  • Užitečné pro callbacks a event handlers

Příklad 3: Optional chaining s bracket notation

const user = {
  name: 'Eve',
  preferences: {
    theme: 'dark',
    language: 'cs'
  }
};

// Dynamický přístup s optional chaining
const key = 'theme';
console.log(user.preferences?.[key]);
// → dark

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

console.log(user2.preferences?.[key]);
// → undefined

// Pole s optional chaining
const users = [
  { name: 'Alice' },
  { name: 'Bob' }
];

console.log(users[0]?.name);  // → Alice
console.log(users[5]?.name);  // → undefined (index 5 neexistuje)

Co se stalo?

  • obj?.[expr] - bezpečný bracket přístup
  • Funguje s dynamickými klíči i poli
  • Vrací undefined pokud vlastnost nebo index neexistuje

Příklad 4: Kombinace s nullish coalescing

const user = {
  name: 'George',
  profile: {
    bio: 'Developer'
  }
};

// Optional chaining + default hodnota
const bio = user?.profile?.bio ?? 'Bez popisku';
console.log(bio);
// → Developer

const user2 = {
  name: 'Helen'
  // profile neexistuje
};

const bio2 = user2?.profile?.bio ?? 'Bez popisku';
console.log(bio2);
// → Bez popisku

// Praktický příklad - API response
const apiResponse = {
  data: {
    user: {
      name: 'Ivan',
      email: 'ivan@example.com'
    }
  }
};

const userName = apiResponse?.data?.user?.name ?? 'Anonym';
console.log(userName);
// → Ivan

const apiResponse2 = {};
const userName2 = apiResponse2?.data?.user?.name ?? 'Anonym';
console.log(userName2);
// → Anonym

Co se stalo?

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

Příklad 5: Optional chaining s delete operátorem

const user = {
  name: 'Jane',
  profile: {
    bio: 'Designer',
    avatar: 'avatar.jpg'
  }
};

// Bezpečné odstranění - OK
delete user?.profile?.avatar;
console.log(user.profile);
// → { bio: 'Designer' }

// Pokud vlastnost neexistuje - žádná chyba
const user2 = {
  name: 'Kate'
  // profile neexistuje
};

delete user2?.profile?.avatar;  // Žádná chyba
console.log(user2);
// → { name: 'Kate' }

Co se stalo?

  • delete obj?.prop - bezpečné odstranění
  • Pokud vlastnost neexistuje, delete nedělá nic (žádná chyba)

Příklad 6: Kdy NEPOUŽÍVAT optional chaining

// ❌ ŠPATNĚ - skrýváš chyby
const user = {
  name: 'Leo',
  age: 30
};

// Pokud víš, že address MUSÍ existovat, nepoužívej ?.
console.log(user?.address?.city);
// → undefined (ale mělo by to být chyba - address chybí!)

// ✅ DOBŘE - pokud address je POVINNÁ, nech to spadnout
// console.log(user.address.city);
// → TypeError: Cannot read property 'city' of undefined
// (Dobrá chyba - upozorní tě na problém!)

// ✅ DOBŘE - používej ?: jen pro OPRAVDU volitelné vlastnosti
const bio = user?.profile?.bio;  // OK - profile je volitelný
const userName = user.name;      // OK - name je povinný

Co se stalo?

  • Nepoužívej ?. všude - skrýváš tím chyby
  • Používej jen pro volitelné vlastnosti
  • Pokud vlastnost musí existovat, nech to spadnout (lepší error handling)

TypeScript

TypeScript přidává typovou kontrolu optional chaining.

Stejné příklady s typy

// Interface s volitelnými vlastnostmi
interface User {
  name: string;
  age: number;
  address?: {  // Volitelná vlastnost
    city: string;
    zip: string;
  };
}

const user: User = {
  name: 'Alice',
  age: 25,
  address: {
    city: 'Praha',
    zip: '11000'
  }
};

// Optional chaining s typy
const city: string | undefined = user.address?.city;
// TypeScript ví, že výsledek může být undefined

// S nullish coalescing
const city2: string = user.address?.city ?? 'Neznámé město';
// TypeScript ví, že výsledek je vždy string

// Funkce s optional chaining
interface Config {
  onSuccess?: () => void;
  onError?: (error: Error) => void;
}

const config: Config = {
  onSuccess: () => console.log('Success!')
};

config.onSuccess?.();  // ✅ OK - TypeScript ví, že je volitelná
config.onError?.(new Error('Test'));  // ✅ OK

// Type narrowing
function getCity(user: User): string {
  if (user.address) {
    // TypeScript ví, že address existuje
    return user.address.city;
  }
  return 'Neznámé město';
}

// Nebo s optional chaining + ??
function getCity2(user: User): string {
  return user.address?.city ?? 'Neznámé město';
}

// Nested optional types
interface Company {
  name: string;
  ceo?: {
    name: string;
    contact?: {
      email: string;
      phone?: string;
    };
  };
}

const company: Company = {
  name: 'TechCorp'
};

const email: string | undefined = company.ceo?.contact?.email;
// TypeScript inferuje: string | undefined

TypeScript přidává:

  • Typovou kontrolu - TypeScript ví, že výsledek může být undefined
  • Type narrowing - lepší inference typů
  • Volitelné vlastnosti - ? v interface
  • Prevenci chyb - upozorní na možné undefined

Rozdíl JS vs TS

JavaScript:

  • Optional chaining funguje bez typové kontroly
  • Musíš ručně kontrolovat undefined
  • Flexibilnější, ale nebezpečnější

TypeScript:

  • TypeScript ví, že výsledek může být undefined
  • Musíš explicitně ošetřit undefined (nebo použít ??)
  • Bezpečnější, prevence chyb
// JavaScript - projde, ale může způsobit problémy
const city = user?.address?.city;
console.log(city.toUpperCase());  // Runtime error pokud city je undefined!

// TypeScript - kontrola
const city: string | undefined = user?.address?.city;
// console.log(city.toUpperCase());  // ❌ Error: Object is possibly 'undefined'

// Musíš ošetřit undefined
if (city) {
  console.log(city.toUpperCase());  // ✅ OK
}

// Nebo s nullish coalescing
const cityUpper = (user?.address?.city ?? 'Unknown').toUpperCase();  // ✅ OK

Tip

💡 Kombinuj ?. s ?? pro default hodnoty:

// ❌ Dlouhé
const city = user && user.address && user.address.city ? user.address.city : 'Unknown';

// ✅ Krátké a čitelné
const city = user?.address?.city ?? 'Unknown';

💡 Nepoužívej ?. všude - skrýváš tím chyby:

// ❌ Špatně - pokud user MUSÍ existovat
function greet(user) {
  console.log(user?.name);  // Skrývá chybu!
}

// ✅ Dobře - pokud user je povinný, nech to spadnout
function greet(user) {
  console.log(user.name);  // Chyba pokud user je null
}

// ✅ Používej ?: jen pro volitelné vlastnosti
function getCity(user) {
  return user.address?.city;  // address je volitelný
}

💡 Optional chaining s funkcemi pro callbacks:

// ✅ Bezpečné volání callbacku
config.onSuccess?.();
config.onError?.(error);

// Místo
if (config.onSuccess) {
  config.onSuccess();
}

Kvíz

Co vypíše tento kód?

const obj = {
  a: {
    b: null
  }
};

console.log(obj?.a?.b?.c);

- ?.c na null vrací undefined, ne null

- - obj?.a{ b: null } (existuje)

  • obj?.a?.bnull (existuje, ale hodnota je null)
  • obj?.a?.b?.cundefined (protože b je null, ?.c vrací undefined)
  • ?. zastaví vyhodnocení když narazí na null nebo undefined
  • Vrací undefined, ne chybu

- ?. předchází chybám

- Vrací undefined, ne objekt

Důležité: Optional chaining ?. zastaví vyhodnocení hned, jak narazí na null nebo undefined, a vrátí undefined!

Důležité: Optional chaining ?. zastaví vyhodnocení hned, jak narazí na null nebo undefined, a vrátí undefined!

🎯 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ě