Proč TypeScript?

TypeScript je nadmnožina JavaScriptu — veškerý platný JS je platný TS. Přidává volitelné statické typy, které kompilátor ověřuje před spuštěním.

❌ JavaScript — chyba za běhu
function soucet(a, b) {
  return a + b;
}

// Zavoláme špatně — žádné varování!
soucet("10", 5); // "105" — ne 15!
soucet();        // NaN
// Chybu zjistíme až od uživatele
✅ TypeScript — chyba při psaní
function soucet(a: number, b: number): number {
  return a + b;
}

// Kompilátor OKAMŽITĚ hlásí chybu:
soucet("10", 5);
// Error: Argument of type 'string'
// is not assignable to parameter
// of type 'number'

Hlavní výhody

  • 🐛 Méně bugů — až 15 % chyb odhalí TypeScript před deploymentem (dle studie Airbnb)
  • 🧠 Lepší autocomplete — VS Code ví, jaké vlastnosti objekt má
  • 📖 Kód jako dokumentace — typy popisují co funkce očekává a vrací
  • 🔄 Bezpečný refactoring — přejmenování se propaguje všude automaticky
  • 👥 Týmová spolupráce — rozhraní je jasně definované
🛠️
TS hřiště v této lekci: Kód vlevo píšete jako TypeScript. Simulátor ho transpiluje a spustí jako JavaScript — výstup console.log() a případné simulované chyby uvidíte vpravo. Pro plnou TS zkušenost doporučujeme typescriptlang.org/play.

Základní typy

TypeScript má všechny JS typy plus několik vlastních. Typová anotace se píše za dvojtečkou:

// Primitivní typy
let jmeno: string = "Jana";
let vek: number = 30;
let aktivni: boolean = true;
let nic: null = null;
let neznamy: undefined = undefined;

// Pole
let cisla: number[] = [1, 2, 3];
let jmena: Array<string> = ["Jana", "Petr"];

// Tuple — pevná délka a typy
let pair: [string, number] = ["Jana", 30];

// Enum — pojmenované konstanty
enum Smer { Nahoru, Dolu, Vlevo, Vpravo }
enum Status { Aktivni = "active", Neaktivni = "inactive" }
const smer: Smer = Smer.Nahoru; // 0

// Any — vypne typovou kontrolu (vyhněte se!)
let cokoliv: any = "text";
cokoliv = 42;       // OK, ale nebezpečné
cokoliv = true;     // OK

// Unknown — bezpečnější alternativa any
let vstup: unknown = getUserInput();
if (typeof vstup === "string") {
  console.log(vstup.toUpperCase()); // OK po type narrowing
}

// Never — funkce nikdy nevrátí
function vyjimka(msg: string): never {
  throw new Error(msg);
}

// Void — funkce nic nevrátí
function loguj(msg: string): void {
  console.log(msg);
}
TS Hřiště — základní typy
▶ Spusťte kód (Ctrl+Enter)

Union a Intersection typy

// Union — jeden z typů (|)
let id: string | number = "abc-123";
id = 42; // také OK

type Vysledek = "uspech" | "chyba" | "cekani";
let stav: Vysledek = "uspech";
// stav = "neznamo"; // ❌ Error!

// Intersection — kombinace typů (&)
type Pojmenovany = { jmeno: string };
type Datovany = { createdAt: Date };
type ZaznamSJmenem = Pojmenovany & Datovany;

const zaznam: ZaznamSJmenem = {
  jmeno: "Jana",
  createdAt: new Date(),
};

🧠 Kvíz: Jaký je rozdíl mezi any a unknown v TypeScriptu?

Interface a Type alias

Pro popis tvaru objektů máme dvě možnosti — interface a type. V praxi jsou téměř zaměnitelné, ale mají drobné rozdíly:

// Interface — pro popis tvaru objektu (preferované)
interface Uzivatel {
  id: number;
  jmeno: string;
  email: string;
  vek?: number;          // ? = volitelné pole
  readonly token: string; // readonly = nelze změnit po přiřazení
}

// Type alias — flexibilnější, lze použít pro union, tuple...
type ID = string | number;
type Souradnice = [number, number];
type Callback = (data: unknown) => void;

// Interface lze rozšiřovat (extends)
interface Admin extends Uzivatel {
  role: "admin" | "superadmin";
  opravneni: string[];
}

// Interface lze "slučovat" (declaration merging)
interface Uzivatel { telefon?: string; } // přidá telefon!

// Type alias nelze slučovat — použijte intersection
type RozsirenyUzivatel = Uzivatel & { prezdivka: string };

// Implementace interface v třídě
class UzivatelService implements Uzivatel {
  id = 1;
  jmeno = "Jana";
  email = "jana@example.com";
  readonly token = "abc123";
}
TS Hřiště — interface a type
▶ Spusťte kód
Kapitola 3 / 8 Další: Funkce →

Typované funkce

// Základní typování funkce
function secti(a: number, b: number): number {
  return a + b;
}

// Arrow funkce
const nasob = (a: number, b: number): number => a * b;

// Volitelné a výchozí parametry
function pozdrav(jmeno: string, pozdrav: string = "Ahoj"): string {
  return `${pozdrav}, ${jmeno}!`;
}

// Rest parametry
function soucetVsech(...cisla: number[]): number {
  return cisla.reduce((a, b) => a + b, 0);
}

// Function overloads — různé signatury
function formuj(hodnota: string): string;
function formuj(hodnota: number): string;
function formuj(hodnota: string | number): string {
  if (typeof hodnota === "number") return hodnota.toFixed(2) + " Kč";
  return hodnota.trim().toUpperCase();
}

// Typ funkce jako parametr (callback)
function transformuj(
  data: number[],
  callback: (item: number) => number
): number[] {
  return data.map(callback);
}

transformuj([1, 2, 3], x => x * 2); // [2, 4, 6]

// Async funkce — vždy vrátí Promise
async function nactiData(url: string): Promise<Uzivatel[]> {
  const res = await fetch(url);
  return res.json();
}
TS Hřiště — typované funkce
▶ Spusťte kód
Kapitola 4 / 8 Další: Generics →

Generics — znovupoužitelné typy

Generics umožňují psát funkce a třídy, které pracují s libovolným typem — přitom zachovávají typovou bezpečnost. Jsou to "typové parametry".

// Základní generická funkce
function identita<T>(hodnota: T): T {
  return hodnota;
}
identita<string>("text"); // "text"
identita(42);              // TypeScript odvodí: number

// Generická rozhraní
interface ApiResponse<T> {
  data: T;
  status: number;
  message: string;
  timestamp: Date;
}

type UserResponse    = ApiResponse<Uzivatel>;
type ProductResponse = ApiResponse<Produkt[]>;

// Generický zásobník (Stack)
class Stack<T> {
  private items: T[] = [];
  push(item: T): void    { this.items.push(item); }
  pop(): T | undefined   { return this.items.pop(); }
  peek(): T | undefined  { return this.items[this.items.length - 1]; }
  isEmpty(): boolean     { return this.items.length === 0; }
  size(): number         { return this.items.length; }
}

const stack = new Stack<number>();
stack.push(1); stack.push(2); stack.push(3);
stack.pop(); // 3

// Constraints — generik musí mít určité vlastnosti
function ziskejId<T extends { id: number }>(objekt: T): number {
  return objekt.id;
}
ziskejId({ id: 42, jmeno: "Jana" }); // 42

// keyof — klíče objektu jako typ
function ziskejVlastnost<T, K extends keyof T>(obj: T, klic: K): T[K] {
  return obj[klic];
}
const email = ziskejVlastnost(uzivatel, "email"); // string
TS Hřiště — Generics
▶ Spusťte kód

🧠 Kvíz: Co znamená constraint <T extends { id: number }>?

Utility Types

TypeScript má vestavěné utility typy pro transformaci existujících typů — místo opisování interface znovu a znovu:

interface Uzivatel {
  id: number;
  jmeno: string;
  email: string;
  heslo: string;
  vek?: number;
}

// Partial<T> — všechna pole volitelná (pro PATCH/update)
type UzivatelUpdate = Partial<Uzivatel>;
// { id?: number; jmeno?: string; email?: string; ... }

// Required<T> — všechna pole povinná
type UzivatelRequired = Required<Uzivatel>;

// Readonly<T> — vše readonly (immutable)
type UzivatelReadonly = Readonly<Uzivatel>;

// Pick<T, K> — vyberte jen některá pole
type UzivatelVerejny = Pick<Uzivatel, "id" | "jmeno" | "email">;
// { id: number; jmeno: string; email: string }

// Omit<T, K> — vynechte pole
type UzivatelBezHesla = Omit<Uzivatel, "heslo">;
// { id: number; jmeno: string; email: string; vek?: number }

// Record<K, V> — objekt s danými klíči a hodnotami
type ErrorMap = Record<string, string>;
// { [key: string]: string }

type StatusMap = Record<"aktivni" | "neaktivni", number>;
// { aktivni: number; neaktivni: number }

// ReturnType<T> — typ návratové hodnoty funkce
function createUser() { return { id: 1, jmeno: "Jana" }; }
type UserType = ReturnType<typeof createUser>;
// { id: number; jmeno: string }

// Parameters<T> — typy parametrů funkce
type CreateUserParams = Parameters<typeof createUser>;

// NonNullable<T> — odstraní null a undefined
type SafeString = NonNullable<string | null | undefined>; // string
TS Hřiště — Utility Types v praxi
▶ Spusťte kód

🧠 Kvíz: Máte interface s 10 poli. Pro PATCH endpoint chcete typ kde jsou všechna pole volitelná. Který utility type použijete?

Kapitola 6 / 8 Další: Cvičení →

Praktické cvičení — Typovaný e-shop modul

Napište TypeScript typy pro mini e-shop modul. Definujte interface pro Produkt, Kosik a Objednavka. Implementujte funkce pridejDoKosiku, vypoctiCelkem a vytvorObjednavku se správnými typy.

📋
Checklist: Interface Produkt (id, nazev, cena, dostupny), interface PolozkaKosiku (produkt, mnozstvi), type Kosik = PolozkaKosiku[], funkce s návratovými typy, Omit pro create payload.
Vaše řešení
▶ Spusťte kód
🏅

Odznak: TypeScript Developer

Zvládáte typy, interface, generics a utility types.

Kapitola 7 / 8 Další: Taháček →

Taháček — TypeScript reference

Základní typy

let s: string; let n: number; let b: boolean;
let pole: number[]; let tuple: [string, number];
let union: string | number; let opt: string | undefined;
let fn: (x: number) => string;

Interface & Type

interface Uzivatel { id: number; jmeno: string; email?: string; }
interface Admin extends Uzivatel { role: string; }
type ID = string | number;
type Status = "active" | "inactive" | "pending";

Generics

function prvni<T>(arr: T[]): T | undefined { return arr[0]; }
interface Response<T> { data: T; status: number; }
class Stack<T> { private items: T[] = []; }

Utility Types — přehled

Partial<T>         // vše volitelné → pro PATCH
Required<T>        // vše povinné
Readonly<T>        // vše readonly
Pick<T, "a"|"b">   // jen vybraná pole
Omit<T, "heslo">   // bez vybraných polí
Record<K, V>        // objekt s danými klíči
NonNullable<T>      // bez null/undefined
ReturnType<typeof fn> // typ návratové hodnoty
Lekce 12 dokončena! Lekce 13: Výkon & SEO →