Přeskočit na obsah
Kurz Reactu1.0.0 beta
CSEN
Kurz Reactu1.0.0 beta
CSEN
🏠 Úvod🧭 Kde začít?🔁 Opakování📄 Taháky📰 Co je novéhoℹ️ O kurzu
JavaScript0/22
TypeScript0/6

Základy TypeScriptu

  • 01 Kam napsat typ (syntaxe TypeScriptu)0/3
  • 02 Typy, které se mění (union a zúžení)0/3

Základy

  • 01 Rychlé opakování základů0/3
  • 02 Stav a události (useState)0/3

Hooky do hloubky

  • 03 Efekty (useEffect)0/3
  • 04 Refy (useRef)0/3
  • 05 Složitější stav (useReducer)0/3
  • 06 Context0/3
  • 07 Vlastní hooky0/3

Formuláře

  • 08 Formuláře a React 19 Actions0/3

Výkon

  • 09 Výkon a renderování0/3

Vzory

  • 10 Návrhové vzory komponent0/3

Ekosystém

  • 11 TypeScript s Reactem0/3
  • 12 Routování (React Router)0/3
  • 13 Načítání dat0/3
  • 14 Správa stavu aplikace0/3

Projekt

  • 15 Závěrečný projekt: Kanban0/2

Shrnutí

  • 16 Shrnutí: principy Reactu

Tvůj účet

Ochrana osobních údajů

TypeScript 01 · Základy TypeScriptu

Kam napsat typ (syntaxe TypeScriptu)

Kdy dvojtečka, kdy <…>, kdy nic. Anatomie zápisu, tahák situací a doplňovačka.

Načítám lekci…

💬 Našel jsi chybu, něco ti není jasné, nebo máš nápad? Napiš mi.
← JS vzory, které v Reactu potkáš všudeTypy, které se mění (union a zúžení) →

Než začneme: štítky na stěhovacích krabicích

Když se stěhuješ, lepíš na krabice štítky: „kuchyň – sklo“, „knihy“, „zimní oblečení“. Krabicím samotným je štítek jedno – věci v nich jsou pořád stejné. Ale stěhováci podle štítků poznají, co se nesmí pokládat pod těžké knihy a kam co odnést. A až je všechno vybalené, štítky strhneš a vyhodíš.

TypeScript jsou štítky na JavaScriptu. Lepíš je na proměnné, parametry a vlastnosti: „tady je číslo“, „tady je uživatel nebo nic“. Kód díky nim nefunguje jinak – ale editor a kompilátor podle nich poznají, když se pokusíš dát sklo pod knihy (předat text tam, kde má být číslo). A při kompilaci se všechny štítky strhnou: prohlížeč dostane čistý JavaScript.

Tahle lekce není o tom, jaké štítky existují, ale kam se lepí: kdy dvojtečka, kdy <…> a kdy nic. Když to máš v malíku, typy v dalších lekcích už tě nezaskočí.

Průhledné a neprůhledné krabice

Na průhlednou krabici štítek nepotřebuješ – je vidět, co v ní je. Stejně tak TypeScript u const count = 0 vidí nulu a sám ví, že jde o číslo. Tomu se říká odvození typu (inference). Štítek musíš nalepit tam, kde dovnitř vidět není: na prázdnou krabici (prázdné pole), na krabici, která zatím zeje prázdnotou (null), nebo na krabici, která teprve přijede (parametr funkce, data z API).

ℹ️ Co tě v lekci čeká
  1. Jedno hlavní pravidlo a anatomie řádku s typem.
  2. Kde se dvojtečka píše a kde (zrádně) ne.
  3. Kdy typ psát a kdy ho nechat odvodit.
  4. Tahák pro typické situace, slovníček symbolů a doplňovačka na procvičení.

1. Jedno hlavní pravidlo

ℹ️ název: Typ

Dvojtečka za názvem čehokoli, co deklaruješ (proměnná, parametr, vlastnost), znamená „je typu“. Pořadí je vždy stejné: nejdřív název, pak dvojtečka, pak typ.

let price: number // proměnná
function f(price: number) // parametr
{ price: number } // vlastnost v typu

Druhá věc, kterou je dobré vědět: typy po kompilaci zmizí – štítky se strhnou. Když z kódu mentálně vymažeš všechny typy, musí zbýt platný JavaScript. To je nejlepší test, jestli je typ na správném místě.

Zkusme to na typické funkci:

function formatPrice(amount: number, currency?: string): string {
return amount + ' ' + (currency ?? 'Kč')
}
  1. amount: number – parametr amount je typu číslo. Název, dvojtečka, typ.
  2. currency?: string – otazník patří k názvu: parametr je nepovinný. Uvnitř funkce může být undefined, proto ?? 'Kč'.
  3. ): string – dvojtečka za závorkou s parametry je typ toho, co funkce vrací. Stejné pravidlo, jen „název“ je tentokrát celé volání funkce.

Teď štítky strhneme:

function formatPrice(amount, currency) {
return amount + ' ' + (currency ?? 'Kč')
}

Zbyl platný JavaScript. Kdyby ne – třeba kdyby z ({ title: string }) zbylo něco, co dělá jinou věc – typ byl na špatném místě. K tomu se dostaneme v další kapitole.

Ukázka

Anatomie řádku – klikni na části kódu

Co vidíš: Několik typických řádků s typy. Každý kousek je obarvený: fialově typ, oranžově syntaxe TypeScriptu (dvojtečky, otazníky, závorky), normálně obyčejný JavaScript. Podtržené kousky mají vysvětlivku.

Vyzkoušej:

  1. V příkladu Proměnná klikni postupně na price, dvojtečku a number. Pod kódem se objeví, co který kousek znamená.
  2. Přepni na Funkce a najdi dvě dvojtečky: jednu u parametru, druhou za závorkou. Klikni na obě a porovnej vysvětlivky.
  3. Projdi Props komponenty a useState. U každého si v duchu vymaž fialové a oranžové části – vždy zbyde platný JavaScript.

Co z toho plyne: Typ je vždy štítek nalepený na konkrétní místo, nejčastěji za dvojtečku. Bez něj zůstane JavaScript, který dělá totéž.

Načítám interaktivní část…

2. Kde se dvojtečka píše a kde ne

Dvojtečka je v JavaScriptu i bez TypeScriptu – v objektech odděluje klíč a hodnotu, v destrukturaci přejmenovává. Proto je to nejčastější zdroj zmatku: stejný znak, tři různé významy. Pomáhá se zeptat: stojí dvojtečka za něčím, co právě deklaruju? Pak je to štítek.

MístoZápisPoznámka
Proměnnálet name: stringJen když TS typ neodvodí z hodnoty.
Parametr(name: string) => …Vždy.
Nepovinný parametr / vlastnostname?: stringOtazník patří k názvu.
Návratová hodnotafunction f(): stringZa ), u arrow funkce před =>.
Vlastnost v interface / type{ name: string }Popis tvaru objektu.
Props komponenty({ name }: Props)Za celou destrukturaci!
Tady dvojtečka NENÍZápisProč
Definice typetype Id = string | numberPojmenováváš typ → rovnítko.
Definice interfaceinterface User { … }Klíčové slovo + jméno + tělo.
Typ pro funkci/hookuseState<User | null>(null)Typ se funkci PŘEDÁVÁ ve špičatých závorkách.
Objekt s hodnotami{ name: 'Jana' }Tady dvojtečka odděluje klíč a HODNOTU.
JSX<Card title="Ahoj" />V JSX žádné typy – TS je kontroluje podle props.
Destrukturace{ title: nadpis }Dvojtečka tu znamená PŘEJMENOVÁNÍ proměnné.
❓ interface, nebo type – kdy co?

Pro popis tvaru objektu (props, data z API) fungují skoro stejně:

interface User { name: string; age?: number }
type User = { name: string; age?: number } // totéž

Rozdíl je v tom, co dalšího umí. Jen type umí pojmenovat cokoli jiného než objekt: union (type Status = 'idle' | 'loading'), tuple, typ funkce. Jen interface jde rozšířit dalším stejnojmenným interface, což se hodí hlavně v knihovnách.

Praktické pravidlo: interface pro tvary objektů a props, type pro všechno ostatní. Hlavně buď konzistentní, nic jiného na tom nezávisí.

⚠️ Dvě nejčastější chyby
// ❌ 1) Typ uvnitř destrukturace – tohle NENÍ typ, ale přejmenování!
function Card({ title: string }) { … } // vytvoří proměnnou "string"
// ✅
function Card({ title }: { title: string }) { … }
function Card({ title }: CardProps) { … }
// ❌ 2) Typy místo hodnot v objektu
const user = { name: string, age: number }
// ✅ typ zvlášť, hodnoty zvlášť
interface User { name: string; age: number }
const user: User = { name: 'Jana', age: 30 }

3. Kdy typ psát a kdy ne

Zpátky ke krabicím. Štítek lepíš tam, kam není vidět, a na krabice, které přijíždějí zvenku. Na průhlednou krabici ho nelepíš – jen bys přidal práci a riziko, že štítek nebude odpovídat obsahu.

// Průhledné krabice – TS vidí dovnitř, štítek nepiš
const count = 0 // number
const names = ['Jana', 'Petr'] // string[]
const [open, setOpen] = useState(false) // boolean
// Krabice přijíždějí zvenku – štítek piš vždy
function greet(name: string) { … } // parametr: kdo ví, co sem kdo pošle
interface CardProps { title: string } // props: totéž pro komponenty
// Neprůhledné krabice – TS nevidí dovnitř, štítek dopiš
const [user, setUser] = useState<User | null>(null) // teď null, později User
const [todos, setTodos] = useState<Todo[]>([]) // prázdné pole – prvky čeho?

Jednoduché pravidlo: typy piš na hranicích – kde data vstupují (parametry, props, API) nebo kde TS nemá z čeho typ poznat. Uvnitř funkcí ho nech pracovat.

✅ Piš vždy🤔 Piš, když TS neodvodí🚫 Nepiš (zbytečné)
Parametry funkcíuseState<User | null>(null)const x: number = 5
Props komponent (interface)useState<Todo[]>([])useState<number>(0)
Tvary dat (interface User)const data: User = await res.json()Parametry inline handlerů v JSX
Data z API (JSON)Samostatné event handleryParametry callbacků (.map(item => …))
Veřejné funkce knihovny / utils[object Object]přiřazení pozdějiNávratový typ jednoduchých funkcí
✨ Jak zjistit, co TS odvodil
Najeď myší na proměnnou ve VS Code. Když tooltip ukazuje přesně to, co chceš, typ nepiš. Když ukazuje any, never[] nebo null, typ dopiš.

4. Tahák: chci otypovat…

Tahák pro situace, které potkáš nejčastěji. Používej ho jako kuchařku: najdi, co právě píšeš, a podívej se, kam štítek patří.

Ukázka

Vyber situaci

Co vidíš: Tlačítka s typickými situacemi, rozdělená na obyčejný JavaScript a React. Ke každé situaci je správný zápis, nejčastější chyba a krátké vysvětlení.

Vyzkoušej:

  1. Klikni na props komponenty. Všimni si chyby { title: string } uvnitř závorek – za chvíli ji uvidíš i v kvízu.
  2. Projdi useState. Štítek je ve špičatých závorkách – typ se hooku předává, ne lepí za dvojtečku.
  3. Podívej se na chybu v catch a data z API. To jsou krabice, které přijely zvenku a nevíš, co v nich je.

Co z toho plyne: Většina situací se opakuje. Až si je párkrát najdeš v taháku, začneš štítky psát na správná místa automaticky.

Načítám interaktivní část…

5. Slovníček symbolů

SymbolPříkladVýznam
:age: number„je typu“
?age?: numbernepovinné (může chybět / být undefined)
|string | null„nebo“ – union
&A & B„a zároveň“ – spojení typů
[]string[]pole
[A, B][string, number]tuple – pole s pevnou délkou
=>(id: number) => voidtyp funkce
<T>Array<User>generikum – typ jako parametr
asdata as User„věř mi“ – přetypování bez kontroly (šetři s ním)
as const['a', 'b'] as constnejpřesnější možný (readonly) typ
!ref.current!„určitě není null“ – bez kontroly
typeoftypeof configtyp z existující hodnoty
keyofkeyof Userunion názvů vlastností: "name" | "age"
❓ Co znamená <T extends { id: number }> (výzva findById)?

Samotné <T> znamená „jakýkoli typ“. Pak by ale TypeScript nedovolil napsat item.id, protože neví, jestli T nějaké id má. extends přidá podmínku: „T může být cokoli, co má aspoň vlastnost id typu number“.

function findById<T extends { id: number }>(items: T[], id: number): T | undefined {
return items.find((item) => item.id === id) // ✅ item.id existuje, protože T ho musí mít
}
findById(products, 1) // T = Product – vrátí Product | undefined
findById(users, 1) // T = User
findById(['a', 'b'], 1) // ❌ string nemá id

Výsledek si pamatuje přesný typ: z findById(products, 1) dostaneš Product se všemi jeho vlastnostmi, ne jen { id: number }. Slovo extends tu neznamená dědičnost jako u tříd, čti ho jako „splňuje“.

6. Jak ti pomůže editor

  • Najetí myší ukáže odvozený typ čehokoli.
  • Ctrl + mezerník v props komponenty nabídne všechny povolené props.
  • F12 na typu (třeba ChangeEvent) skočí na jeho definici.
  • Ctrl + . (Quick Fix) na parametru s any nabídne „Infer parameter types from usage“.
  • Chybové hlášky čti odspodu. Poslední řádek dlouhé chyby bývá ten podstatný („Property 'email' is missing…“).

Procvič si to: doplňovačka

Doplň do políček, co tam patří – typ, symbol, nebo nic. Každé cvičení trénuje jedno místo, kam se štítek lepí. Pamatuj na průhledné krabice: někdy je správná odpověď nechat políčko prázdné.

Tip: prázdné políčko znamená „sem nepíšu nic“ – i to může být správná odpověď. Enter = zkontrolovat.Vyřešeno 0 / 16
1. Parametr funkce
function double(n) {
  return n * 2
}
2. Návratová hodnota
function greet(name: string) {
  return 'Ahoj ' + name
}
3. Nepovinný parametr
function greet(name: string, excited boolean) {
  return excited ? name + '!' : name
}
4. Tvar objektu
interface User {
  name string
  age number     // nepovinné
}
5. Hodnota vs. typ
interface User { name: string }

const jana: User = { name:  }
6. Typ jako union
type Status  'idle' | 'loading' | 'error'
7. Props komponenty
interface AvatarProps {
  src: string
  size?: number
}

function Avatar({ src, size = 40 }) {
  return <img src={src} width={size} />
}
8. Callback v props
interface ListProps {
  items: string[]
  onSelect:    // dostane index vybrané položky
}
9. useState s null
const [user, setUser] = useState(null)
10. useState s prázdným polem
const [todos, setTodos] = useState([])
11. Kdy typ nepsat
const [count, setCount] = useState(0)
12. Proměnná, která se naplní později
let selected = null

// později: selected = jana   (jana je User)
13. Samostatný event handler
const handleChange = (e) => {
  setName(e.target.value)
}
14. Async funkce
async function loadUser(id: number):  {
  const res = await fetch('/api/users/' + id)
  return res.json()
}
15. Generická funkce
function first(items: T[]): T | undefined {
  return items[0]
}
16. Dvojice z funkce (tuple)
function minMax(nums: number[]) {
  return [Math.min(...nums), Math.max(...nums)] 
}

Kde je chyba?

Kvíz Co je špatně?
function Badge({ label: string, color: string }) {
return <span style={{ color }}>{label}</span>
}
Kvíz Proč setItems([...items, 'nový']) hlásí chybu?
const [items, setItems] = useState([])
Kvíz Která verze je správně?
// A
const handleClick: (e: MouseEvent<HTMLButtonElement>) => void = (e) => { … }
// B
const handleClick = (e: MouseEvent<HTMLButtonElement>) => { … }
// C
const handleClick = (e) : MouseEvent<HTMLButtonElement> => { … }
Kvíz Kam patří typ u arrow komponenty?
const Card = ({ title }) => <h2>{title}</h2>

Rozcvička

Výzva

Typy místo any

Rozcvička

Vyměň dvakrát any za skutečný typ a doplň, co funkce vracejí.

Zadání najdeš v komentářích v kódu níže – na začátku souboru a u míst označených TODO.

Načítám interaktivní část…

Výzvy

V obou výzvách je hotový kód plný any – krabic bez štítků. Tvým úkolem je štítky nalepit na správná místa: nejdřív u obyčejných funkcí, pak v React komponentě. Na stránce se nic nezmění; rozdíl uvidí jen TypeScript.

✨ Automatická kontrola
Obě výzvy mají typové testy. Spusť npm run typecheck:challenges – dokud máš v kódu any, uvidíš chyby „Unused '@ts-expect-error' directive“ (znamená to, že TS nezachytil chybu, kterou zachytit má). Když jsou typy správně, výstup je prázdný.
Výzva

Kam s typy? – obyčejné funkce

Lehká

Sedm malých funkcí, sedm míst, kam typ patří. Výstup na stránce se nezmění – rozdíl uvidí jen TypeScript. Jaké typy kam patří, je v komentářích v kódu.

Zadání najdeš v komentářích v kódu níže – na začátku souboru a u míst označených TODO.

Načítám interaktivní část…

Výzva

Kam s typy? – React komponenta

StředníBonus · zdarma po přihlášení

Typická místa v React komponentě: props, callback, useState a event handler. Co kde má být za typ, je v komentářích v kódu.

🔓 Bonusová výzva – zdarma po přihlášení

Střední a těžké výzvy se odemknou, jakmile se přihlásíš. Stejně jako celý kurz jsou zdarma – stačí e-mail, žádné heslo ani platba.

Jak nakládáme s tvými údaji

Shrnutí

  • Typy jsou štítky na JavaScriptu: kód nemění, jen ho kontrolují, a při kompilaci se strhnou. Po jejich vymazání musí zbýt platný JavaScript.
  • název: Typ – dvojtečka za tím, co deklaruješ (proměnná, parametr, vlastnost), znamená „je typu“. Návratový typ za závorkou parametrů: function f(): T.
  • Typ props za celou destrukturací: ({ a, b }: Props). Uvnitř { } dvojtečka přejmenovává!
  • type X = … (rovnítko), interface X { … }, typ pro hook ve špičatých závorkách: useState<T>().
  • Štítky na hranice a neprůhledné krabice (parametry, props, tvary dat, null, prázdná pole); průhledné krabice nech TS odvodit.
  • Nevíš? Najeď myší – editor ti typ řekne.
🧩 Odkud se berou věci, které tu nejsou definované (products)
products – ze souboru src/course/fakeApi.ts. Falešné API kurzu: data a funkce, které předstírají server (se zpožděním, občas i s chybou). Ve skutečné aplikaci by tu bylo volání fetch().
export interface Product {
id: number
name: string
category: 'ovoce' | 'zelenina' | 'pečivo' | 'mléčné'
price: number
inStock: boolean
}
export const products: Product[] = [
{ id: 1, name: 'Jablko', category: 'ovoce', price: 12, inStock: true },
{ id: 2, name: 'Banán', category: 'ovoce', price: 8, inStock: true },
{ id: 3, name: 'Hruška', category: 'ovoce', price: 15, inStock: false },
{ id: 4, name: 'Mrkev', category: 'zelenina', price: 6, inStock: true },
{ id: 5, name: 'Rajče', category: 'zelenina', price: 9, inStock: true },
{ id: 6, name: 'Okurka', category: 'zelenina', price: 19, inStock: false },
{ id: 7, name: 'Rohlík', category: 'pečivo', price: 3, inStock: true },
{ id: 8, name: 'Chléb', category: 'pečivo', price: 45, inStock: true },
{ id: 9, name: 'Mléko', category: 'mléčné', price: 22, inStock: true },
{ id: 10, name: 'Sýr eidam', category: 'mléčné', price: 39, inStock: true },
{ id: 11, name: 'Jogurt', category: 'mléčné', price: 14, inStock: false },
{ id: 12, name: 'Pomeranč', category: 'ovoce', price: 11, inStock: true },
]
CSS třídy jako row, stack, card, list, btn, input nebo muted jsou hotové styly kurzu v src/styles.css (row = prvky vedle sebe, stack = pod sebou, card = rámeček, muted = šedý text).