od Podstaw
1 godz. 54 min · Typescript · Full-stack i Programowanie
Adam GospodarczykZacznijmy od tego, że JavaScript jest dynamicznie typowany. Oznacza to, że typy zmiennych mogą się zmieniać w czasie wykonywania programu, a my nie mamy nad nimi kontroli. A po co nam ta kontrola? Między innymi po to, aby przypadkowo nie dodać typu number do string lub przekazać do funkcji nieprawidłowe danych. Ogromną zaletą jest to, że o tego typu błędach dowiadujemy się już na etapie pisania kodu a nie dopiero w trakcie jego wykonywania... na produkcji.
Prawdopodobnie znasz mechanizm intellisense, czyli inteligentnego podpowiadania kodu przez edytor. Pisząc kod w TypeScript, tworzysz definicje typów dotyczących Twojej aplikacji. W ten sposób dostęp do definicji klas i właściwości obiektów masz właściwie na wyciągnięcie myszki. Wystarczy "hover" na funkcji aby uzyskać szczegółowe informacje, które pomogą Ci w pisaniu kodu. Oprócz tego otrzymasz również automatyczne podpowiedzi w trakcie dostępu do właściwości i metod. Nic tylko pisać kod!
Nie musisz przepisywać całego projektu. TypeScript stanowi nadzbiór JavaScriptu. Zatem cały Twój projekt jest z nim w 100% kompatybilny, a Ty możesz stopniowo dodawać definicje typów. Nawet nie będziesz wiedział kiedy typy pojawią się w całej Twojej aplikacji. To daje Ci również możliwość uczenia się TypeScriptu w trakcie jego wdrażania. W tym kursie opanujesz podstawy a później... sam zobaczysz!
Ten kurs został stworzony z myślą o programistach, którzy podstawy JavaScriptu mają już za sobą i chcą poznać zalety statycznego typowania oferowanego przez TypeScript. Na początku Kursu zaczynamy również od krótkiej powtórki najważniejszych elementów samego JS.
3.8+
Funkcje, podobnie jak inne rodzaje danych, mogą posiadać swój typ.
Jak to dokładnie wygląda w TypeScripcie dowiemy się w tym odcinku.
Zacznijmy od tego, że zdefiniujemy tutaj funkcję wykorzystując function expression.
Z tą różnicą jednak, że nie przejdziemy
od razu do definiowania samej funkcji, tylko na początku określimy jej typ.
Jak sama nazwa wskazuje funkcja ta będzie zamieniać liczbę na tekst,
w związku z tym musi przyjąć jakiś
parametr. No i tym parametrem w tym przypadku będzie liczba.
Następnie, warto by było żebyśmy określili co taka funkcja może zwracać.
I tutaj również z pomocą arrow function możemy to zdefiniować.
Dzięki temu mamy jasno określone, że ta funkcja będzie przyjmować parametr, który
będzie liczbą a następnie będzie zamieniać go na ciąg znaków.
Zwróć uwagę, że mamy tutaj let, czyli
podkreślam, że jest to po prostu zmienna. Więc teraz nic nie stoi na przeszkodzie,
abym teraz do tej zmiennej przypisał tę funkcję, której typ już określiliśmy.
No i funkcja ta przyjmuje parametr, który
jest liczbą a następnie zwraca tekst. Zwróć uwagę, że w związku z tym, że w tym
miejscu określiłem typ tej funkcji, TS automatycznie wie, że tym parametrem
jest liczba a następnie, że ta funkcja zwraca tekst.
Więc jeżeli tutaj zwrócilibyśmy po prostu liczbę no to mielibyśmy błąd.
A tak TypeScript po prostu dba o to, abyśmy
zachowali poprawny typ. I teraz wywołując tę funkcję otrzymuje właściwy wynik.
Także z tego przykładu musisz wiedzieć,
że możemy określać typy parametrów i zresztą robiliśmy to już niejednokrotnie oraz
również możemy określać jakiego rodzaju dane może zwracać funkcja.
Dzięki temu mamy pełną kontrolę nad danymi,
które wchodzą do funkcji i nad danymi, które z niej wychodzą.
Poza tym zyskujemy tutaj ogromną przewagę w momencie, gdy używamy tych funkcji,
bo możemy łatwo podejrzeć w jaki sposób możemy z niej korzystać.
Mam nadzieję, że na ten moment jest to dla Ciebie jasne.
Zresztą jest to dość intuicyjne.
Przejdźmy jednak do innego, nieco bardziej złożonego przykładu, w którym zdefiniujemy
z pomocą słowa kluczowego type strukturę obiektu Song.
Będzie on miał właściwości takie jak ID oraz podstawowe informacje o utworze.
Następnie będzie nam potrzebna mała
tablica utworów - będzie ona pełnić funkcję małej bazy danych.
Do tego, abyśmy mogli stworzyć funkcję,
która będzie aktualizować te wpisy. W tym celu definiuję nowy typ i znowu odwołuję
się do słowa kluczowego type, dzięki któremu mogę określić sam typ i w tym przypadku
będzie to typ funkcji. Zrobię to analogicznie jak w tym miejscu,
przy czym zdefiniowanie tego typu w ten
sposób umożliwia mi podłączenie go do jakiejkolwiek funkcji chcę.
No ale przejdźmy już do jego definicji.
Funkcja ta będzie przyjmować dwa argumenty.
Będzie to identyfikator utworu oraz dane, które chcemy zaktualizować.
Następnie funkcja ta może zwracać dwa rodzaje danych.
W przypadku gdy utwór zostanie poprawnie
zaktualizowany, zwrócę tutaj zaktualizowany obiekt tego utworu.
W przeciwnym razie będzie to wartość false.
Więc jak widzisz wykorzystałem tutaj
union type, który świetnie się tutaj sprawdził. I tym samym mam już wszystko,
żeby przejść do zdefiniowania naszej funkcji.
Tutaj po prostu zaczynam od zadeklarowania
zmiennej, która będzie przyjmować typ naszej funkcji.
Następnie do tej zmiennej przypisuję
funkcję, przyjmującą dwa argumenty i ponownie zwracam Twoją uwagę, że tutaj już
nie muszę określać typu, ponieważ zrobiłem to przed chwilą.
Wewnątrz tej funkcji musimy dokonać
weryfikacji czy utwór o podanym identyfikatorze w ogóle istnieje.
Dlatego też musimy odnaleźć jego indeks.
Do znajdowania obiektów tablicy świetnie sprawdza się funkcja findIndex. Po prostu
do jej call backu przekazuję odpowiedni warunek i zostanie nam zwrócony indeks
elementu, którego identyfikator będzie pasował do naszego argumentu.
Drugim krokiem tutaj będzie sprawdzenie czy w ogóle ten utwór został odnaleziony.
Jeżeli tak to aktualizujemy ten wpis przekazanymi danymi.
I tutaj oczywiście nie dokonujemy żadnej
walidacji, ale na potrzeby tego przykładu nie ma to akurat znaczenia.
W każdym razie w momencie gdy utwór
nie zostanie znaleziony, zwracamy tak jak wspomniałem wcześniej wartość false.
No i w tym momencie mamy pięknie
zdefiniowaną funkcję, którą w momencie gdy będziemy używać i przekażemy do niej
jakieś dane, które nie pasują do tego układu,
od razu TypeScript będzie nas o tym informował.
Mało tego, jeżeli nawet przekażemy odpowiedni argument, no to w dalszym ciągu
TypeScript informuje nas o tym, że nie możemy tutaj przypisać takiego obiektu.
A gdyby nam było tego mało to od razu mamy
też informację jakiego rodzaju właściwości taki obiekt musi posiadać.
Dlatego też wystarczy, że zmienię wywołanie tej funkcji i wszystko będzie w porządku.
Mamy tutaj nawet potwierdzenie tego, że dane faktycznie zostały zaktualizowane.
Dodatkowo jeżeli chcielibyśmy to możemy
sprawdzić czy utwory faktycznie zostały zaktualizowane. No i już na pierwszy rzut
oka mamy tę informację, że faktycznie tak się stało.
Zatem nasza funkcja zadziałała a my
wykorzystaliśmy podstawowe zalety definiowania typów funkcji.
W tym temacie na ten moment będzie to już wszystko.
Jednak przygotuj się na to, że wielokrotnie będziemy do tego wracać i przyglądać się
temu jak wyglądają typy funkcji w różnego rodzaju przypadkach.
Na ten moment to wszystko i mam nadzieję, że słyszymy się za chwilę.
Typy funkcji · 1 min
let numberToText: (num: number) => string
numberToText = (num) => num.toString()
numberToText(5) /*?*/Typy obiektów i funkcji · 3 min
type Song = { id: number; title: string; duration: number; genre: string }
const songs: Song[] = [
{ id: 1, title: "Eye of the tiger", duration: 246, genre: "rock" },
{ id: 2, title: "Carry On Wayward Son", duration: 283, genre: "rock" },
]
type updateSong = (id: number, data: Song) => Song | BooleanFunkcja update · 5 min
const update: updateSong = (songId, data) => {
const index = songs.findIndex(({ id }) => id === songId)
if (index > -1) {
return (songs[index] = data)
}
return false
}
update(2, { id: 2, title: "Eyes", duration: 10, genre: "rock" }) /*?*/
songs /*?*/