Lekce 2 - Funkce v TypeScriptu
V minulé lekci, Úvod do TypeScriptu, jsme se podívali na úplné základy TypeScriptu a vysvětlili si, proč je dobré ho používat.
Dnes se podíváme na funkce, které se od klasického JavaScriptu příliš neliší.
Funkce
Funkce v TypeScriptu se prakticky neliší od těch z JavaScriptu až na jednu věc, a to je typování. U funkce v TypeScriptu se typuje jak parametr funkce, tak její výstup. A to i v případě, že funkce žádný výstup nemá. Typování nemusíme používat, ale to by byla hloupost, jelikož se jedná o silnou zbraň TypeScriptu.
Typování
Pro začátek si napíšeme úplně základní metodu na sečtení dvou čísel bez typování:
function sečti(x, y) { return x + y; }
Můžeme vidět, že by člověk nepoznal rozdíl mezi TypeScriptem a JavaScriptem.
Nyní ale využijeme typování a funkci si přepíšeme tak, jak by měla vypadat napsaná v TypeScriptu.
function add(x: number, y: number): number { return x + y; }
Takhle napsaná funkce, vypadá a slouží mnohem lépe.
Někteří by mohli namítnout, že typování parametrů je zbytečné, ale
má to také své výhody. Když voláme metodu, hned na první pohled je
jasné, co metoda přijímá a vrací, aniž bychom četli dokumentační
komentář. Také to má nespornou výhodu v tom, že nám TypeScript dokáže
oznamovat chybu, kdybychom například vkládali datový typ string
do čísla.
Volitelné parametry
Za zmínku také stojí takzvané nepovinné (volitelné) parametry. Hodí se to zejména na metody, které vrací srozumitelný výsledek i bez všech možných parametrů.
Ukážeme si to na této metodě:
function vratJmeno(jmeno: string, prijmeni: string): string { return jmeno + " " + prijmeni; }
Řekněme, že je možné, aby člověk neměl příjmení. Jenže stále při volání této funkce musíme vložit parametr. Mohli bychom metodu například využít takto:
let celeJmeno = vratJmeno("Josef", NULL);
A právě od toho tu existují volitelné parametry. Naší metodu
vratJmeno'()
předěláme tak, aby příjmení nebylo povinné:
function vratJmeno(jmeno: string, prijmeni?: string): string { if (prijmeni) return jmeno + " " + prijmeni; else return jmeno; }
Takto upravenou metodu můžeme zavolat následovně:
let celeJmeno = vratJmeno("Josef");
Zařídili jsme to pomocí znaku ?
hned za názvem proměnné.
Aby metoda fungovala správně vždy, musíme také trochu předělat tělo
metody a ověřit, jestli nám byl předán parametr prijmeni
nebo
ne.
Dalším způsobem, jak zařídit volitelné parametry, je předdefinovat parametr v hlavičce metody:
function vratJmeno(jmeno: string, prijmeni = "Novák"): string { return jmeno + " " + prijmeni; }
V parametrech metody nemusíme ani definovat typ proměnné
prijmeni
, protože to děláme již přiřazením. Také odpadá
kontrolování, zda bylo příjmení předáno, protože se nikdy nestane, že
by metoda neměla příjmení.
Pokud nyní metodu zavoláme:
let celeJmeno = vratJmeno("Adam");
bude v proměnné celeJmeno
uložena hodnota
Adam Novák
.
Libovolný počet parametrů
Co když budeme chtít předat více parametrů, ale zároveň nebudeme vědět, kolik jich bude? Samozřejmě můžeme vytvořit metodu ve stylu:
function vratJmeno(param1?: string, param2?: param3?: string, param4?: string): string { //tělo metody }
V tento moment můžeme vložit klidně až 4 parametry a něco s nimi dělat. Co když budeme chtít 50? Není asi moc dobré psát 50 parametrů do hlavičky metody, že?
Možná již zkušenější programátoři v duchu křičí "POLE". Ano, skoro jste to uhádli, protože se jedná o velice podobný styl zápisu. Jenže existuje ale ještě jedna možnost:
function vratJmenoAVlastnosti(jmeno: string, ...vlastnosti: string[]): string { return jmeno + " je " + vlastnosti.join(", "); }
Pomocí těch ...
říkáme, že předem nevíme, kolik přijde
parametrů. A jak jsem říkal, že se jedná o podobný styl zápisu jako u
pole, všimněte si přítomných []
, přesně jako kdybychom pouze
přijímali obyčejné pole. Metodou join()
si pouze pomáháme
spojit jednotlivé stringy do jednoho řetězce.
Pokud vytvoříme takovouto metodu, můžeme jí zavolat například takto:
let vlastnostiCloveka = vratJmenoAVlastnosti("Petr", "laskavý", "vysoký", "hubený");
Výstup takového kódu bude:
Petr je laskavý, vysoký, hubený
Přetěžování metody
Při psaní kódu se může stát, že jedna funkce bude velmi podobná druhé. Můžeme si ušetřit práci tím, že funkci takzvaně přetížíme. To znamená, že budeme mít několik hlaviček metod se stejným názvem, ale jinými parametry, které do ní vkládáme. Při psaní takové funkce musíme sami určit, co se stane s různými vstupy:
function hledej(ulice: number, mesto: string): void; function hledej(ulice: string, mesto: string): void; function hledej(ulice, mesto): void { if (typeof ulice !== 'number') { console.log(`Adresa je ${ulice}, ${mesto}.`); } else if (typeof ulice !== 'string') { console.log(`${mesto} nemá ulice, ale číslo domu je ${ulice}.`); } } hledej('Lázeňská', 'Mariánské Lázně'); // Adresa je Lázeňská, Mariánské Lázně. hledej(122, 'Králíikov'); // Králičkov nemá ulice, ale číslo domu je 122.
Pokud někteří z vás mají zkušenosti s přetěžováním funkcí z jiných jazyků, možná jste teď trochu zmateni. Hlavičky metod píšeme pod sebe a dalo by se říci, že v našem případě píšeme tělo pro tři metody zároveň. Proto musíme rozlišit o jaký vstup se jedná a dle toho se rozhodovat.
Doufám, že se vám problematika funkcí podařila pochopit a tímto bych ukončil tuto lekci.
V následujícím cvičení, Řešené úlohy k 1.-2. lekci v TypeScriptu, si procvičíme nabyté zkušenosti z předchozích lekcí.