Techniki Zaawansowane
2 godz. 35 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.
TypeScript umożliwia stosunkowo prostą migrację istniejących projektów JavaScript. W kursie na przykładzie zostały omówione trzy strategie, dzięki którym jesteśmy w stanie dodać statyczne typowanie do istniejącego kodu. W procesie migracji najważniejsze jest to, że przepisywanie kodu jesteśmy w stanie uzależnić również od poziomu naszej wiedzy na temat TypeScriptu i stopniowo dodawać kolejne elementy.
Na pierwszy rzut oka można uznać, że TypeScript tylko dodaje nam pracy, wymuszając dodatkową konfigurację oraz opisywanie typów. Mało tego zwiększa barierę wejścia w projekt dla mniej doświadczonych programistów. Trudno temu zaprzeczyć ALE - korzyści płynące ze statycznego typowania które wpływają na zmniejszenie liczby błędów oraz wykrywanie ich nawet na poziomie pisania kodu, oszczędzają czas który normalnie poświęcilibyśmy na późniejsze debugowanie aplikacji. Poza tym zwiększenie stabilności aplikacji daje szerokie korzyści biznesowe, które wielokrotnie wynagradzają nam czas wymagany na pisanie dodatkowej składni.
JavaScript jest językiem dynamicznie typowanym. W trakcie wykonywania programu, zmienne mogą zmieniać swój typ a my nie zawsze mamy nad tym świadomą kontrolę. Tylko ... po co nam ta kontrola? Główną zaletą statycznego typowania jest to aby uniknąć sytuacji w których przypadkowo przypisujemy tekst do zmiennej która powinna zawierać liczbę lub sytuacji w której przekazujemy do funkcji nieprawidłowe dane. Taki rodzaj pomyłek generuje błędy odniesienia (eng. ReferenceError), które zatrzymują działanie skryptu i są momentami bardzo uciążliwe do wykrycia. Dzięki statycznemu typowaniu, jesteśmy w stanie wykrywać je na etapie pisania kodu.
TypeScript na przestrzeni ostatnich lat zyskuje ogromną popularność w społeczności programistów JavaScript i coraz częściej jest nieodłącznym elementem ofert o pracę. W przypadku firm nastawionych na rozwój rozbudowanych aplikacji JavaScript już teraz jest w zasadzie standardem. Biorąc pod uwagę fakt, że najnowsze frameworki (np. Nest.js) wykorzystują TypeScript domyślnie, nauka tej technologii ma ogromny sens w kontekście rozwoju jako programista. I ostatnim argumentem za tym aby wziąć TypeScript na poważnie jest to, że stoi za nim firma Microsoft a on sam rozwijany jest już niemal 10 lat.
Ten kurs został stworzony z myślą o programistach, którzy podstawy TypeScriptu mają już za sobą i chcą poznać jego zaawansowane techniki. Aby w pełni wykorzystać wiedzę z tego kursu, niezbędna jest również zaawansowana znajomość JavaScriptu a w szczególności jego elementów prowadzonych w wersji ES6+. Zdecydowanie polecamy przerobienie kursu Podstawowego TypeScript, który znajdziesz na eduweb, przed korzystaniem z tego materiału.
3.9+
Nadszedł czas abym pokazał ci w jaki sposób możesz definiować własne type guard
aby dostosować je bardziej do swoich potrzeb mało tego okazują
się one szczególnie przydatne w momencie gdy mamy do czynienia z literałami obiektu tym
razem nie będziemy korzystać z klas tylko do określenia struktury obiektów użyj
interfejsów jeżeli teraz utworzę funkcję która będzie przyjmować
albo jeden albo drugi interfejs a następnie w zależności od tego z
jakim typem danych będziemy mieć do czynienia będziemy zwracać odpowiednio tytuł
lub nazwę playlisty do zdefiniowania logiki tej funkcji za chwilę
sobie przejdziemy a teraz po prostu spróbujmy ją wywołać zarówno
dla utworu oraz playlisty zwróć uwagę że w żaden sposób
nie określam tutaj typu tego obiektu który przekazuje a pomimo tego
typescript jest z tym jak najbardziej okej wynika to z faktu o
którym już wspominałem na przestrzeni tego i poprzedniego kursu a mianowicie faktu
że typescript do porównywania typów wykorzystuje tak zwany duck typing krótko
przypomnę że chodzi tutaj o zachowanie kształtu obiektu więc tak długo
jak przekazany przez nas obiekt posiada kształt który pasuje do jednego z tych interfejsów
wszystko jest w porządku na przykład jeżeli tutaj dodałbym jakąś inną właściwość no
to mamy jasny błąd informujący nas o tym że nie możemy tego zrobić w
każdym razie teraz nasuwa się pytanie w jaki sposób możemy sprawdzić czy przekazany
argument jest utworem bądź playlistą w poprzedniej lekcji pokazałem
ci że jesteśmy w stanie wykorzystać asercję typów do tego aby sprawdzić czy występuje
konkretna właściwość danego obiektu i faktycznie z perspektywy typescriptu
jest to poprawne rozwiazanie natomiast jak zapewne pamiętasz typescript
na ten moment nie wie dalej czy mamy do czynienia z utworem czy playlistą aby
odczytywać właściwości naszego obiektu dalej będziemy musieli posługiwać sie tutaj asercją
aby tego uniknąć możemy zdefiniować własny type guard który
będzie przekazywał typescriptowi odpowiednią informację o typie w tym momencie
nasuwa się pytanie w jaki sposób taki type guard utworzyć otóż
nie jest to wcale takie trudne ponieważ type guard to po prostu funkcja której
zadaniem jest zwrócenie prawdy lub fałszu proponuję więc
abyśmy utworzyli sobie nową funkcję do której będziemy przekazywać ten jeden argument
pochodzący stąd następnie typem tego argumentu będzie utwór lub
playlista no bo tylko takich rodzajów danych spodziewamy się wewnątrz tej funkcji
a następnie podobnie jak wcześniej a następnie w związku z tym
że sprawdzamy czy przekazany argument jest typu song wystarczy
że po prostu sprawdzimy czy właściwość title istnieje wewnątrz niego w
tym momencie typescript informuje nas tutaj o ewentualnym błędzie który wystąpi
w momencie gdy przekażemy tutaj playlistę no bo faktycznie w żaden sposób nie
bronimy się tutaj przed tym że typ media będzie typu playlist możemy
to jednak zrobić wykorzystując następującą konstrukcję
możemy to jednak zrobić lekko modyfikując naszą funkcję przede
wszystkim zamienimy tutaj typ przekazanego argumentu na any i choć
z jednej strony pozbyliśmy się tutaj naszego błędu to niestety straciliśmy
również informację o typie ale zobaczmy teraz co stanie się w momencie
gdy wykorzystamy naszą funkcję okazuje się
że pomimo tego że utworzyliśmy tutaj naszą funkcję która zwraca prawdę lub fałsz
no to typescript dalej nie posiada tutaj informacji o tym czy
mamy do czynienia z utworem czy też z playlistą dlatego musimy mu tą informację
przekazać dodając informację o zwracanym typie w efekcie otrzymujemy
tutaj type guard który daje typescriptowi informację o tym że
w tym miejscu mamy do czynienia z utworem i w tym momencie wystarczy
że naprawię jeszcze to odwołanie no i wszystko jest tutaj w porządku zatem
podsumowując zwróć uwagę że pomimo tego że wykorzystujemy tutaj literały
obiektu typescript akceptuje je jako argumenty naszej funkcji ze
względu na to że pasują one kształtem do interfejsów które zdefiniowaliśmy
tutaj następnie aby poradzić sobie z odróżnieniem tych typów
wykorzystaliśmy custom type guard czyli po prostu utworzoną funkcję
która zwraca prawdę lub fałsz ale też z informacją o tym
jaki typ weryfikujemy i dopiero na podstawie takich informacji
typescript jest w stanie samodzielnie określić w którym miejscu mamy do czynienia
z jakim rodzajem danych oczywiście też nie chciałbym abyś zrozumiał
że custom type guard jesteśmy w stanie wykorzystywać wyłącznie z literałami obiektów równie
dobrze wewnątrz tej funkcji mogłyby się znaleźć operatory typeof albo
instanceof tutaj nic nie stoi nam na przeszkodzie o ile
pamiętamy o tym aby zwrócić informację który typ tutaj weryfikujemy
ostatecznie już to co mi się tutaj jeszcze nie podoba to fakt że
wykorzystujemy tutaj typ any ale również informuje nas tutaj eslint
o tym że nie powinniśmy tego robić jeżeli wrócimy teraz do poprzedniego
zapisu czyli song lub playlist no to mamy tutaj błąd który
również mieliśmy w poprzednim odcinku i z nim akurat możemy sobie poradzić
wykorzystując asercję typów czyli konkretnie robię teraz tak
no i teraz nasz type guard jest perfekcyjnie napisany
ani eslint ani typescript nie informuje nas o żadnym błędzie
zatem na temat customowych type guardów to już wszystko ja
dziękuję ci teraz za uwagę i nie pozostaje mi nic innego jak po prostu
zaprosić cię do kolejnej lekcji
interfaces · 1 min
interface Song {
title: string;
}
interface Playlist {
name: string;
}isSong · 5 min
function isSong(media: Song | Playlist): media is Song {
return (media as Song) !== undefined;
}play() · 4 min
function play(media: Song | Playlist) {
if (isSong(media)) {
console.log(media.title);
} else {
console.log(media.name);
}
}