TypeScript je jednou z technologií, které používám ve chvíli, kdy projekty v JavaScriptu přerostou rámec malých skriptů a potřebují pevnější kontrakty, bezpečnější refaktoring a předvídatelnější aplikační architekturu.
Používám jej pro prohlížečové aplikace, integrace API, strukturovanou frontendovou logiku a kódové báze, v nichž data procházejí více vrstvami a nesprávné předpoklady mohou být nákladné.
Pro mě TypeScript není pouze JavaScript s doplňkovou syntaxí.
Jeho skutečná hodnota spočívá v tom, že dělá aplikační kontrakty explicitními a umožňuje kompilátoru i vývojovým nástrojům odhalit celé kategorie chyb ještě předtím, než se kód dostane do produkce.
Jak používám TypeScript
TypeScript používám například pro:
- prohlížečové aplikace,
- frontendovou aplikační logiku,
- klienty REST API,
- strukturovaný stav aplikace,
- znovupoužitelné moduly,
- transformaci dat,
- integrace prohlížečových API,
- rozsáhlé kódové báze v JavaScriptu,
- refaktoring,
- sdílené datové kontrakty.
Je obzvlášť užitečný ve chvíli, kdy aplikace obsahuje tolik vzájemně souvisejících částí, že je obtížné spolehlivě sledovat implicitní předpoklady JavaScriptu.
TypeScript a JavaScript
TypeScript staví na JavaScriptu.
Platné koncepty JavaScriptu zůstávají nadále důležité.
Stále potřebuji rozumět:
- běhovému prostředí prohlížeče,
- event loopu,
- promises,
- closures,
- modulům,
- DOM API,
- asynchronnímu chování.
TypeScript kolem tohoto běhového prostředí přidává statický typový systém.
Prohlížeč nakonec vždy vykonává JavaScript.
TypeScript zlepšuje způsob, jakým kód navrhuji a ověřuji před tím, než se do této fáze dostane.
Statické typování
Jedním z hlavních důvodů, proč TypeScript používám, je statické typování.
Funkce může své požadavky vyjádřit explicitně.
Například:
function calculateTotal(price: number, quantity: number): number {
return price * quantity;
}
Kompilátor dokáže odhalit nesprávné použití ještě před spuštěním programu.
S rostoucím počtem míst, na nichž se funkce v rozsáhlejší aplikaci znovu používají, roste i hodnota této kontroly.
Explicitní kontrakty
Typy fungují jako kontrakty mezi jednotlivými částmi aplikace.
Klient API může například vracet:
interface Project {
id: number;
title: string;
active: boolean;
}
Kód, který tento výsledek používá, ví, jakou strukturu má očekávat.
To zlepšuje:
- čitelnost,
- automatické doplňování,
- refaktoring,
- odhalování chyb.
Kontrakt se stává součástí zdrojového kódu, místo aby existoval pouze v dokumentaci nebo v paměti vývojáře.
Rozhraní
Rozhraní používám k popisu struktur objektů a hranic mezi komponentami.
Jsou užitečná například pro modely:
- odpovědí API,
- konfigurace,
- stavu uživatelského rozhraní,
- kontraktů služeb.
Například:
interface UserSettings {
darkMode: boolean;
language: string;
}
Je tak okamžitě zřejmé, jaká data k danému modelu patří.
Typové aliasy
Typové aliasy jsou užitečné v případech, kdy je vhodnější typ vyjádřit pomocí:
- union typů,
- primitivních typů,
- složených struktur.
Například:
type Status = "idle" | "loading" | "success" | "error";
To je výrazně bezpečnější než předávat aplikací libovolné řetězce.
Union typy
Union typy mi umožňují reprezentovat kontrolovanou množinu možných hodnot.
Například:
type Theme = "light" | "dark" | "system";
Kompilátor pak může neplatné hodnoty odmítnout.
To je užitečné například pro:
- režimy,
- stavy,
- stavy API,
- varianty funkcí.
Diskriminované union typy
U složitějšího stavu aplikace poskytují diskriminované union typy robustní způsob, jak modelovat vzájemně se vylučující stavy.
Například:
type Result<T> =
| { status: "loading" }
| { status: "success"; data: T }
| { status: "error"; message: string };
Díky tomu je výrazně obtížnější reprezentovat neplatné kombinace stavů.
Uživatelské rozhraní může každý stav zpracovat explicitně.
Zužování typů
TypeScript dokáže typ hodnoty zúžit na základě kontrol prováděných za běhu.
Například:
if (result.status === "success") {
console.log(result.data);
}
Uvnitř této větve TypeScript rozumí tomu, která varianta je aktivní.
Kód řízený stavem je díky tomu bezpečnější a zároveň čitelnější.
Null a undefined
JavaScriptové aplikace často pracují s chybějícími hodnotami.
TypeScript tuto situaci dělá mnohem explicitnější.
Typ jako:
string | null
jasně sděluje, že hodnota může chybět.
Dávám přednost explicitním nullable typům před spoléháním na nepříjemná překvapení za běhu aplikace.
Je to obzvlášť důležité při práci s:
- API,
- DOM prvky,
- uživatelskými vstupy,
- volitelnou konfigurací.
Striktní režim
U seriózních projektů dávám přednost striktnímu nastavení TypeScriptu.
Přísnější pravidla kompilátoru odhalí více chybných předpokladů včas.
Mohou odhalit problémy týkající se:
- nullability,
- implicitních typů,
- nebezpečného přístupu k vlastnostem,
- neúplných kontraktů.
Volnější nastavení může usnadnit migraci, ale striktní typování obvykle přináší vyšší dlouhodobou hodnotu.
Odvozování typů
Neanotuji ručně každou proměnnou.
Odvozování typů v TypeScriptu je dostatečně silné na to, aby mnoho typů určilo z kontextu.
Například:
const count = 5;
nepotřebuje explicitní anotaci number.
Anotace přidávám tam, kde zpřehledňují veřejné kontrakty nebo zabraňují nejednoznačnosti.
Cílem je bezpečnost a čitelnost, nikoli maximální množství typové syntaxe.
Generika
Generika umožňují znovupoužitelnému kódu zachovat typovou informaci.
Například:
function first<T>(items: T[]): T | undefined {
return items[0];
}
Tato funkce pracuje s mnoha typy a přitom stále vrací správně odvozený typ.
Generika používám pro skutečně znovupoužitelné abstrakce, jako jsou:
- obaly API,
- kolekce,
- výsledkové typy,
- pomocné utility.
Vyhýbám se zbytečné složitosti generik tam, kde je jednodušší konkrétní typ srozumitelnější.
Utility typy
TypeScript obsahuje utility typy, které usnadňují transformace modelů.
Patří mezi ně například:
Partial,Pick,Omit,Readonly,Record.
Jsou užitečné, když je potřeba z jednoho modelu odvodit jiný bez ručního duplikování definic.
Například:
type ProjectPreview = Pick<Project, "id" | "title">;
Související kontrakty tak zůstávají synchronizované.
Data pouze pro čtení
Tam, kde je to vhodné, používám readonly typy k vyjádření toho, že by data neměla být přímo měněna.
Například:
readonly id: number;
nebo:
ReadonlyArray<Project>
To pomáhá podporovat vzory neměnného stavu.
Neměnnost
Neměnnému stavu dávám přednost tam, kde usnadňuje pochopení toku aplikace.
Místo nepředvídatelné mutace sdílených objektů kód vytváří nový stav.
Tím se omezuje množství skrytých závislostí a tento přístup dobře zapadá do:
- rozhraní řízených stavem,
- reaktivních architektur,
- předvídatelných transformací dat.
Typový systém TypeScriptu může pomoci tato očekávání vynucovat.
Výčty a literálové typy
TypeScript podporuje výčty, ale často zvažuji, zda jednodušší reprezentaci neposkytne union typ řetězcových literálů.
Pro mnoho stavů aplikace:
type Direction = "forward" | "backward";
je snadno serializovatelný a přehledný.
Konkrétní reprezentaci volím podle skutečného případu použití, nikoli podle jednoho univerzálního pravidla.
Funkce
U funkcí, které tvoří důležité hranice systému, používám explicitní typy parametrů a návratových hodnot.
Například:
function parseResponse(input: unknown): Project[]
jasně sděluje, co funkce přijímá a co slibuje vrátit.
Při refaktoringu je to velmi cenné.
Unknown vs. any
Pro externí data, která ještě nebyla ověřena, dávám přednost typu unknown před any.
any v praxi vypíná typovou kontrolu.
unknown nutí kód hodnotu před použitím ověřit.
To je obzvlášť důležité pro:
- JSON,
- odpovědi API,
- zprávy prohlížeče,
- externí knihovny.
Omezování typu any
Existují případy, kdy je any praktické, zejména při integraci knihoven třetích stran s neúplnými typovými definicemi.
Rozsáhlé používání any však popírá velkou část důvodů, proč TypeScript vůbec používat.
Snažím se proto udržovat nebezpečné hranice malé a explicitní.
Validace za běhu
Typy TypeScriptu za běhu aplikace neexistují.
Samotná deklarace typu proto neprokazuje, že externí data skutečně mají danou strukturu.
Pokud API vrátí neplatný JSON, kompilátor TypeScriptu nemůže běžící aplikaci automaticky ochránit.
Proto rozlišuji mezi:
Typem při kompilaci
a
validací za běhu
Obojí je důležité.
Externí data
Data překračující hranice aplikace považuji za nedůvěryhodná.
Patří sem:
- odpovědi REST API,
- lokální soubory,
- uživatelský vstup,
- úložiště prohlížeče,
- zprávy WebSocketu.
Než s nimi začnu pracovat jako s důvěryhodným typovaným objektem, ověřuji jejich strukturu.
JSON
TypeScript přirozeně zapadá do aplikací založených na JSON.
Po parsování a validaci dat používám typované modely.
Typický tok může vypadat takto:
JSON
↓
validace za běhu
↓
typovaný model
↓
aplikační logika
Je to bezpečnější než okamžité přetypování libovolných dat.
Typové aserce
Typové aserce mohou být užitečné v případech, kdy TypeScript postrádá informaci, kterou aplikace skutečně zná.
Přetypování jako:
data as Project
však data nevaliduje.
Aserce nepoužívám pouze k umlčení kompilátoru.
Pokud hodnota pochází z externího zdroje, bývá robustnějším řešením validace za běhu.
REST API
TypeScript je obzvlášť přínosný při integraci REST API.
Mohu definovat modely pro:
- požadavky,
- odpovědi,
- stránkování,
- chyby.
Například:
interface ApiResponse<T> {
data: T;
success: boolean;
}
Klienti API jsou díky tomu srozumitelnější a snadněji se mění.
Kontrakty API
Pokud mám pod kontrolou klienta i server, snažím se udržovat kontrakt API explicitní.
Změny, jako je přejmenování pole, pak mohou vyvolat chyby kompilátoru napříč celou kódovou bází namísto toho, aby za běhu aplikace selhaly bez zjevného upozornění.
To je jeden z nejsilnějších praktických přínosů TypeScriptu ve větších projektech.
WordPress REST API
TypeScript dobře funguje pro rozhraní využívající WordPress REST API.
Mohu vytvářet typované reprezentace:
- příspěvků,
- vlastních typů obsahu,
- taxonomií,
- odpovědí vlastních endpointů.
Údržba vlastních WordPress aplikací je díky tomu snazší než při zpracování každé odpovědi jako libovolného objektu.
Prohlížečové aplikace
TypeScript používám pro prohlížečové aplikace, v nichž JavaScript zajišťuje více než jen jednoduché vylepšení stránky.
Patří sem například:
- nástroje,
- editory,
- mediální aplikace,
- simulace,
- interaktivní rozhraní.
S rostoucím stavem a chováním aplikace roste i hodnota explicitních typů.
Prohlížečová API
TypeScript poskytuje rozsáhlé typové definice pro prohlížečová API.
To zlepšuje vývoj při práci s funkcemi jako:
- File API,
- Canvas,
- Web Workers,
- Web Audio,
- WebGL.
Editor může přímo rozumět objektům prohlížeče a kontraktům jejich metod.
Snižuje se tak potřeba pamatovat si ručně každý podpis API.
Manipulace s DOM
DOM obsahuje mnoho hodnot, které mohou být potenciálně null.
Například:
const element = document.querySelector("#app");
Výsledek může být null.
TypeScript nutí kód s touto možností počítat, místo aby automaticky předpokládal, že prvek vždy existuje.
Jde o jednoduchý příklad toho, jak typová bezpečnost předchází křehkým předpokladům ve frontendu.
Typy událostí
Události prohlížeče lze také explicitně typovat.
To pomáhá například při zpracování:
- vstupních událostí,
- událostí ukazatele,
- událostí klávesnice,
- drag-and-drop,
- vlastních událostí.
Obsluha události pak ví, jaké vlastnosti má k dispozici.
Web Workers
TypeScript je užitečný také v aplikacích využívajících Web Workers.
Zprávy předávané mezi vlákny mohou mít explicitní typy.
Například:
Hlavní vlákno
→ typovaný požadavek
→ Worker
Worker
→ typovaná odpověď
→ Hlavní vlákno
Tím se omezuje množství chyb v komunikačních protokolech.
Integrace WebAssembly
Když JavaScript nebo TypeScript komunikuje s WebAssembly, jsou jasně definované typy na hranici obou prostředí obzvlášť užitečné.
Obě prostředí si mohou předávat:
- buffery,
- čísla,
- strukturovaná metadata.
Rozhraní mezi JavaScriptovou aplikací a kompilovaným modulem udržuji malé a explicitní.
Zpracování souborů
Prohlížečové aplikace pro práci se soubory často obsahují několik stavových přechodů.
Například:
Vybrán soubor
↓
Validace
↓
Zpracování
↓
Výsledek
↓
Stažení
TypeScript pomáhá tyto stavy i související data explicitně reprezentovat.
Je to obzvlášť užitečné, pokud jsou součástí řešení také Web Workers nebo WebAssembly.
Stav aplikace
Typy používám k promyšlenému modelování stavu aplikace.
Místo jednoho volného objektu s mnoha volitelnými vlastnostmi dávám přednost strukturám, které jasně reprezentují platné stavy.
Díky tomu je snazší odpovědět na otázky:
- Jaká data v tomto okamžiku existují?
- Které akce jsou platné?
- Které hodnoty mohou chybět?
Dobře navržený stav snižuje potřebu obranných podmínek v celé kódové bázi.
Moduly
TypeScriptové projekty organizuji do modulů s jasně vymezenou odpovědností.
Jednotlivé moduly mohou obsahovat například:
- přístup k API,
- doménové modely,
- stav,
- renderování,
- pomocné utility,
- integrace s prohlížečem.
Vyhýbám se jednomu obrovskému souboru obsahujícímu veškerou aplikační logiku.
Hranice modulů usnadňují pochopení závislostí.
ES moduly
Moderní vývoj v TypeScriptu využívá standardní koncepty modulů JavaScriptu.
Pracuji s:
export
import
a vytvářím tak explicitní závislosti mezi soubory.
Je to lepší než spoléhat na globální proměnné.
Zapouzdření
Ne každá funkce nebo typ by měly být exportovány.
Interní implementační detaily ponechávám soukromé uvnitř modulu, pokud je jiné části aplikace nepotřebují.
Menší veřejná rozhraní usnadňují pozdější refaktoring.
Třídy
TypeScript podporuje třídy a objektově orientovanou architekturu.
Třídy používám tam, kde poskytují užitečný model pro:
- stavové služby,
- integrace,
- znovupoužitelné komponenty.
Nenutím každou část aplikační logiky do třídy.
Pro bezstavové transformace bývají funkce a obyčejné objekty často jednodušší.
Rozhraní vs. třídy
Rozhraní popisuje kontrakt.
Třída poskytuje implementaci.
Tento rozdíl zachovávám zřetelný.
Aplikační kód může například záviset na rozhraní:
StorageService
zatímco různé implementace mohou používat:
LocalStorage
IndexedDB
Remote API
Tím se snižuje provázanost.
Dependency injection
U větších aplikací usnadňují explicitní závislosti testování a nahrazování komponent.
Místo vytváření služeb hluboko uvnitř aplikační logiky je lze předávat komponentám, které je potřebují.
Rozhraní TypeScriptu umožňují tyto kontrakty snadno vyjádřit.
Zpracování chyb
Očekávaná selhání modeluji explicitně.
Operace může skončit například:
- úspěchem,
- chybou validace,
- síťovou chybou,
- nedostupným prostředkem.
U běžných výsledků aplikace se nespoléhám na nezachycené výjimky.
Konkrétní model závisí na dané funkci, ale typový systém může pomoci zajistit, že se na chybové stavy nezapomene.
Promises
Promises a async/await používám pro asynchronní operace, jako jsou:
- požadavky API,
- operace se soubory,
- prohlížečová API.
TypeScript umožňuje zachovat explicitní typ výsledné hodnoty.
Například:
async function loadProjects(): Promise<Project[]>
jasně vyjadřuje asynchronní kontrakt.
Async/Await
Pro vícekrokové asynchronní workflow často dávám přednost async/await, protože zachovává přehledný tok řízení.
Například:
fetch
↓
ověření odpovědi
↓
parsování
↓
transformace
↓
aktualizace stavu
Současně vhodně zpracovávám odmítnutí i zrušení operace.
Fetch API
Tam, kde je to vhodné, používám pro HTTP komunikaci prohlížečové Fetch API.
TypeScript zlepšuje okolní kód, ale vrácený JSON automaticky nevaliduje.
Stále ověřuji:
- HTTP stav,
- očekávanou strukturu odpovědi,
- chybové odpovědi.
Samotná existence rozhraní nečiní síťovou odpověď důvěryhodnou.
AbortController
U požadavků nebo dlouhotrvajících operací, které mohou přestat být relevantní, používám tam, kde je to vhodné, mechanismy pro zrušení, například AbortController.
To je užitečné například tehdy, když:
- uživatel přejde jinam,
- novější požadavek nahradí starší,
- je operace ručně zrušena.
Omezení zbytečné práce zlepšuje výkon i správnost stavu.
Striktní hranice aplikace
V místech, kde data vstupují do systému, chci nejsilnější validaci.
Patří sem například:
API
Soubor
Uživatelský vstup
Úložiště
Zpráva Workeru
Jakmile data projdou validovanou hranicí, může zbytek aplikace pracovat s pevnějšími předpoklady.
Výsledkem je čistší kód, než kdyby bylo nutné stejnou strukturu opakovaně kontrolovat na mnoha místech.
Local Storage
TypeScript může pomoci modelovat data uložená v perzistentních mechanismech prohlížeče.
localStorage však stále ukládá řetězce.
Uložená data navíc mohou pocházet ze starší verze aplikace.
Při jejich načítání je proto validuji, místo abych předpokládal, že stále odpovídají aktuálnímu rozhraní.
IndexedDB
Pro rozsáhlejší data na straně klienta mohou prohlížečové aplikace používat IndexedDB.
TypeScript může poskytnout jasné modely pro uložené záznamy i přístupové vrstvy.
Tam, kde je to možné, odděluji detaily perzistence od aplikačního stavu.
Refaktoring
TypeScript přináší významnou hodnotu při refaktoringu.
Pokud změním:
- parametr funkce,
- název vlastnosti,
- návratový typ,
- rozhraní,
kompilátor může určit závislý kód, kterému je potřeba věnovat pozornost.
Velké změny jsou díky tomu bezpečnější než při spoléhání pouze na ruční vyhledávání.
Přejmenování
Moderní IDE mohou využít znalost kódové báze poskytovanou TypeScriptem a přejmenovávat symboly strukturálně.
Je to výrazně bezpečnější než slepé nahrazování textu.
Nástroj rozumí referencím, nikoli pouze shodám znakových řetězců.
Automatické doplňování
Typové informace zvyšují také rychlost vývoje.
Editory mohou přesně nabízet:
- metody,
- názvy vlastností,
- informace o parametrech,
- dokumentaci.
To je obzvlášť užitečné při práci s rozsáhlými prohlížečovými API nebo aplikačními modely.
Mrtvý kód a nesprávné předpoklady
Kompilátor může odhalit cesty kódu, které již neodpovídají aktuální architektuře.
Například hodnota, která dříve byla volitelná a nově je povinná, může odhalit staré kontroly nebo neúplnou inicializaci.
Typy jsou díky tomu užitečné nejen při novém vývoji, ale i při údržbě existujících systémů.
Kompilátor TypeScriptu
Kompilátor TypeScriptu převádí TypeScript na JavaScript, který může vykonat cílové běhové prostředí.
Konfigurace kompilátoru řídí například:
- míru striktnosti,
- modulový systém,
- cílovou verzi jazyka,
- zahrnuté knihovny.
Konfiguraci kompilátoru uchovávám ve správě verzí.
Je součástí aplikační architektury.
Cílová prostředí
Výstupní JavaScript může cílit na různé schopnosti běhového prostředí.
Cíl volím podle:
- podporovaných prohlížečů,
- prostředí nasazení,
- build nástrojů.
Vyhýbám se zbytečné transpilaci moderních funkcí pro zastaralá prostředí, pokud to projekt nevyžaduje.
Build nástroje
TypeScript se běžně používá společně s bundlery a build nástroji.
Podle projektu mohou tyto nástroje zajišťovat:
- bundlování modulů,
- vývojové servery,
- optimalizaci,
- produkční buildy.
Build pipeline udržuji tak jednoduchou, jak to aplikace umožňuje.
Malý prohlížečový nástroj automaticky nepotřebuje složitý frontendový framework a komplexní build architekturu.
Source maps
Během vývoje source maps výrazně usnadňují ladění zkompilovaného TypeScriptu.
Umožňují vývojářským nástrojům prohlížeče propojit vykonávaný JavaScript s původním zdrojovým kódem v TypeScriptu.
To je důležité při diagnostice chyb ve vývojovém i produkčním prostředí.
Linting
Statická analýza může vhodně doplňovat kompilátor TypeScriptu.
Linter může odhalovat problémy související s:
- stylem,
- podezřelými vzory,
- nepoužívaným kódem,
- pravidly konkrétního projektu.
Takové nástroje používám tam, kde mají skutečnou hodnotu a dokážou problémy odhalovat automaticky.
Vyhýbám se tomu, aby se samotná konfigurace lintingu stala cílem.
Formátování
Konzistentní formátování omezuje zbytečné rozdíly ve správě verzí.
Automatické formátování je užitečné, protože vývojáři nemusí trávit čas debatami o mezerách a drobných stylistických volbách.
Tým nebo projekt se tak při review může soustředit na skutečné chování kódu.
Testování
TypeScript zlepšuje nejen produkční, ale také testovací kód.
Testy těží ze stejných:
- modelů,
- rozhraní,
- automatického doplňování,
- kontrol kompilátoru.
Testy zaměřuji na důležité chování, například:
- stavové přechody,
- transformace,
- validaci,
- zpracování API.
Mockování
Jasně definovaná rozhraní usnadňují nahrazování externích závislostí během testů.
Službu komunikující se vzdáleným API lze například nahradit předvídatelnou testovací implementací.
Aplikační logiku tak lze testovat bez potřeby skutečného síťového přístupu.
Bezpečnost
TypeScript zvyšuje správnost kódu z pohledu vývojáře, ale není bezpečnostní hranicí.
Prohlížeč zůstává pod kontrolou uživatele.
Citlivé operace, jako jsou:
- autorizace,
- práce s tajnými údaji,
- ověřování plateb
musí být stále vynucovány na serveru.
Typová bezpečnost nemůže z frontendového kódu udělat důvěryhodnou backendovou logiku.
Tajné údaje
Soukromé klíče API nepatří do TypeScriptových balíčků doručovaných do prohlížeče.
Cokoli odeslané do prohlížeče lze zkontrolovat.
Pokud API vyžaduje tajný přístupový údaj, směruji požadavek přes vhodný backend.
Validace vstupu
Uživatelský vstup zůstává nedůvěryhodný i v případě, že je hodnota formuláře uložena do proměnné typu string.
Typ mi říká pouze to, že aplikace přijala text.
Neříká mi, že je tento text bezpečný nebo platný.
Hodnoty proto stále validuji podle pravidel aplikace.
XSS
Při vykreslování externího obsahu zohledňuji rizika cross-site scriptingu.
Dávám přednost bezpečným DOM API a bezpečnému renderování frameworku před vkládáním libovolného nedůvěryhodného HTML.
Typy mohou pomoci aplikaci strukturovat, ale bezpečnost výstupu stále závisí na způsobu, jakým jsou hodnoty vykreslovány.
Výkon
TypeScript se během kompilace odstraňuje, takže většina vlastností výkonu za běhu je ve skutečnosti vlastností JavaScriptu.
Optimalizuji oblasti, jako jsou:
- aktualizace DOM,
- velké kolekce,
- zbytečné síťové požadavky,
- opakované výpočty,
- renderovací smyčky.
Typový systém zlepšuje architekturu, ale nenahrazuje profilování výkonu.
Velikost balíčku
Rozsáhlé frontendové aplikace mohou postupně nashromáždit významné množství závislostí.
Zvažuji, zda funkcionalita knihovny ospravedlňuje její dopad na:
- velikost balíčku,
- spouštění aplikace,
- údržbu.
TypeScript funguje bez problémů s nativními prohlížečovými API.
Používání TypeScriptu nevyžaduje rozsáhlý framework.
Nativní prohlížečová API
Tam, kde schopnosti nativní platformy řeší problém čistě, jim dávám přednost.
Může jít například o:
- Fetch,
- File API,
- Canvas,
- Web Workers,
- Web Audio,
- WebGL.
Vestavěné typové definice prohlížeče v TypeScriptu činí práci s těmito API obzvlášť příjemnou.
TypeScript a Three.js
U 3D aplikací v prohlížeči může TypeScript poskytovat pevnější kontrakty pro:
- objekty scény,
- geometrii,
- stav simulace,
- konfiguraci.
S rostoucí 3D aplikací je stále cennější udržovat stav i rozhraní objektů explicitní.
TypeScript a WebGL
Přímý vývoj ve WebGL zahrnuje velké množství číselných parametrů, bufferů a změn stavu.
TypeScript může část integračních chyb omezit tím, že explicitně definuje struktury na straně aplikace.
Nenahrazuje znalost grafického API, ale zlepšuje architekturu okolní aplikace.
TypeScript a Web Workers
U výpočetně náročných prohlížečových aplikací často chci, aby zprávy Workerů dodržovaly definovaný protokol.
Například:
type WorkerMessage =
| { type: "process"; data: ArrayBuffer }
| { type: "cancel" };
Údržba hlavního vlákna i Workeru je díky tomu jednodušší.
TypeScript a WordPress
TypeScript může vhodně doplňovat WordPress, pokud frontend obsahuje rozsáhlejší vlastní aplikační logiku.
WordPress a PHP zůstávají serverovou částí systému.
TypeScript může poskytovat strukturovanou aplikační vrstvu v prohlížeči.
Například:
WordPress / PHP
↓
REST API
↓
JSON
↓
TypeScriptová aplikace
Každá technologie tak může obsluhovat vrstvu, pro kterou se nejlépe hodí.
TypeScript a Python
V systémech kombinujících Python backend s frontendem v prohlížeči poskytuje TypeScript užitečný kontrakt na straně klienta.
Typická architektura může vypadat například takto:
Python backend
↓
REST API
↓
TypeScript frontend
Hranice API zůstává explicitní a testovatelná.
TypeScript a vývoj s podporou AI
TypeScript je obzvlášť užitečný při vývoji softwaru s podporou AI, protože kompilátor poskytuje okamžitou validační vrstvu nad vygenerovaným kódem.
Vygenerovaný kód může působit věrohodně, a přesto:
- nesprávně volat funkci,
- používat neexistující vlastnost,
- porušovat rozhraní.
Silné typování mnoho takových chyb rychle zviditelní.
Vygenerovanou architekturu a chování přesto stále kontroluji ručně.
Migrace z JavaScriptu
Existující JavaScriptové aplikace lze na TypeScript migrovat postupně.
Úplný přepis není vždy nutný.
Rozumná migrace může začít takto:
kritické moduly
↓
kontrakty API
↓
sdílené modely
↓
zbývající aplikační kód
Míru striktnosti lze také zvyšovat postupně s tím, jak se kódová báze lépe typuje.
Postupná migrace omezuje riziko.
Udržovatelnost
Hlavním důvodem, proč TypeScript používám, je udržovatelnost.
JavaScript je mimořádně flexibilní.
Tato flexibilita se však stává nebezpečnou, pokud rozsáhlá aplikace závisí na nezdokumentovaných předpokladech.
TypeScript mnoho těchto předpokladů převádí na explicitní kontrakty.
Budoucí vývoj tak snáze odpovídá na otázky:
- Co tato funkce očekává?
- Může tato hodnota chybět?
- Které stavy jsou platné?
- Co toto API vrací?
Velkou část odpovědi poskytuje samotný kód.
Omezování typové složitosti
Kódová báze v TypeScriptu může být až zbytečně chytrá.
Složité podmíněné typy, hluboce vnořená generika a typové programování mohou někdy systém učinit hůře pochopitelným než samotný problém.
Pokročilé typování používám tam, kde přináší jasnou hodnotu.
Jednoduché rozhraní je často lepší než působivý typový výraz, který nikdo nechce udržovat.
TypeScript v mém technologickém stacku
TypeScript běžně používám společně s technologiemi, jako jsou:
- JavaScript,
- HTML a CSS,
- REST API,
- JSON,
- WordPress REST API,
- prohlížečová API,
- Web Workers,
- WebAssembly,
- Canvas,
- WebGL,
- Three.js,
- backendy v Pythonu nebo PHP.
TypeScript kolem těchto prohlížečových a API technologií poskytuje typově bezpečnou aplikační vrstvu.
Proč používám TypeScript
TypeScript používám ve chvíli, kdy se JavaScriptová aplikace stane natolik důležitou, že už nejsou přijatelné implicitní předpoklady.
Jeho hodnota nespočívá pouze v automatickém doplňování nebo doplňkové syntaxi.
Dělá datové struktury, kontrakty funkcí a stavy aplikace explicitními.
Tím zlepšuje refaktoring, pomáhá odhalovat chyby dříve a usnadňuje pochopení rozsáhlejších kódových bází.
Běhovým prostředím zůstává JavaScript.
TypeScript kolem něj poskytuje inženýrskou disciplínu.
Právě proto TypeScript používám pro prohlížečové aplikace a integrace, u nichž záleží na udržovatelnosti, správnosti a dlouhodobém rozvoji.