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.
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
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é
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);
}
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";
}
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();
}
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
🧠 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
🧠 Kvíz: Máte interface s 10 poli. Pro PATCH endpoint chcete typ kde jsou všechna pole volitelná. Který utility type použijete?
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.
Produkt (id, nazev, cena, dostupny), interface PolozkaKosiku (produkt, mnozstvi), type Kosik = PolozkaKosiku[], funkce s návratovými typy, Omit pro create payload.Odznak: TypeScript Developer
Zvládáte typy, interface, generics a utility types.
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