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 jenullneboundefined, 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í
undefinedpokud 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 hodnotouobj?.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?.b→null(existuje, ale hodnota jenull)obj?.a?.b?.c→undefined(protožebjenull,?.cvracíundefined)?.zastaví vyhodnocení když narazí nanullneboundefined- 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 →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
- 05.1 Vytvoření objektu
- 05.2 Vlastnosti
- 05.3 Metody objektu
- 05.4 This keyword
- 05.5 Destructuring objektů
- 05.6 Spread u objektů
- 05.7 Optional chaining
- 05.8 Nullish coalescing
- 05.9 Object.keys/values/entries
- 05.10 Computed properties
- 05.11 Getters a setters
- 05.12 Object.freeze/seal
Struktura lekcí (souborový strom)
- 1.1 Úvod do JavaScriptu a TypeScriptu
- 1.2 Nastavení prostředí
- 1.3 První program
- 1.4 Proměnné: var, let, const
- 1.5 Datové typy - přehled
- 1.6 String (řetězce)
- 1.7 Number (čísla)
- 1.8 Boolean (pravda/nepravda)
- 1.9 Null a Undefined
- 1.10 Type Inference vs Annotations
- 1.11 Aritmetické operátory
- 1.12 Porovnávací operátory
- 1.13 Logické operátory
- 1.14 Komentáře
- 1.15 Console metody
- 03.01 Deklarace funkce
- 03.02 Function Expression
- 03.03 Arrow Functions
- 03.04 Parametry a argumenty
- 03.05 Return hodnoty
- 03.06 Výchozí parametry
- 03.07 Rest parametry
- 03.08 Co je Scope
- 03.09 Lexikální Scope
- 03.10 Řetězec Scope
- 03.11 Globální Scope
- 03.12 Životní Cyklus Proměnných
- 03.13 Omezení Scope
- 03.14 Použití Closures
- 03.15 Callback funkce
- 03.16 Higher-order Functions
- 03.17 IIFE
- 03.18 Void funkce
- 03.19 Rekurze
- v přípravě
- v přípravě
- v přípravě
- v přípravě
- 01 — Co je Next.js
- 02 — Vytvoření projektu
- 03 — Struktura projektu (app/)
- 04 — Page komponenty (page.js / page.tsx)
- 05 — Layout komponenty (layout.js / layout.tsx)
- 06 — File-based routing
- 07 — Dynamické routy ([id]/page.js)
- 08 — Link komponenta (navigace)
- 09 — Image komponenta (next/image)
- 10 — Metadata (title, description, Open Graph)
- 11 — Loading UI (loading.js / loading.tsx)
- 12 — Error handling (error.js / error.tsx)
- 13 — Not Found (not-found.js / not-found.tsx)
- v přípravě
- v přípravě
- v přípravě