Czym jest TypeScript?
Technicznie rzecz ujmując TypeScript (TS) to nadzbiór dla popularnego JavaScriptu (JS). W praktyce oznacza to, że wzbogaca on istniejący już język, dodając do niego nową składnię, zatem nie jest samodzielnym językiem programowania. Pisząc kod w TypeScript nadal będziemy korzystać z dobrze znanego nam JavaScriptu, dzięki temu nie musimy uczyć się od podstaw - trzeba jedynie poznać różnice pomiędzy tymi dwoma językami i nauczyć się kilku nowych zasad, które panują w świecie języków statycznie typowanych (o tym już za chwilę).
Warto w tym miejscu zaznaczyć, że przeglądarki nie rozumieją czym jest TypeScript, więc próba uruchomienia kodu napisanego w tym języku zakończy się niepowodzeniem. Rozwiązaniem tego problemu jest kompilacja kodu TS do JS. Na szczęście twórcy dostarczyli do tego celu kompilator który pozwoli nam osiągnąć taki efekt.
Statyczne i dynamiczne języki
Wspomniałem, że jeśli chcemy korzystać z możliwości, które daje nam TypeScript, to musimy poznać kilka zasad - przede wszystkim postaramy się zrozumieć różnicę pomiędzy językami dynamicznymi (do których zalicza się JavaScript), a tymi statycznymi (tu skupimy się oczywiście na głównym temacie artykułu).
Na wykresie przedstawiłem podział języków programowania ze względu na ich typ - wyróżniłem także dwa interesujące nas najbardziej. Jak widzisz znajdują się ona na dwóch przeciwległych końcach. Odległość od środka nie ma tu żadnego znaczenia, chodzi jedynie o znaczenie do której grupy należy dany język, można zatem powiedzieć, że TypeScript ma zupełnie inne założenia u podstaw niż JavaScript.
Podział języków programowania ze względu na ich typ
Krótka charakterystyka poszczególnych wariantów:
typowanie statyczne - oznacza, że sprawdzenie (walidacja) typów odbywa się na poziomie kompilacji języka (compile-time validation) - przed uruchomieniem aplikacji. Typy poszczególnych zmiennych, parametrów funkcji, pól w klasach, itd. muszą być znane z wyprzedzeniem. Do tej grupy zaliczany jest TypeScript.
typowanie dynamiczne - walidacja odbywa się dopiero w momencie działania programu (runtime validation), co może prowadzić do znacznie większej liczby problemów związanych z niepoprawnymi danymi. Jednym z przedstawicieli takich języków jest JavaScript.
typowanie silne - jeśli spojrzysz jeszcze raz na powyższy wykres, to okaże się, że silne typowanie nie wyklucza typowania dynamicznego. Istnieją języki które jednocześnie są typowane dynamicznie i silnie. O typowaniu silnym mówimy, jeżeli dany język nie pozwala na niejawną konwersję pomiędzy typami - przykładem takiego zachowania może być Python, który nie pozwoli na dodanie do siebie wartości typu
int
orazstring
.
typowanie słabe - jest przeciwieństwem typowania silnego, a co za tym idzie, dozwolona jest tutaj niejawna konwersja typów. Idealnym przykładem będzie JavaScript - tu bez problemu możemy dodać do siebie typ
string
oraznumber
. W tym przypadku dojdzie do konkatenacji stringów, a więc typnumber
został niejawnie przekształcony na typstring
.
Na pierwszy rzut oka zalety statycznie typowanych języków mogą nie być oczywiste. Jak wspomniałem wcześniej, walidacja typów dopiero w momencie działania aplikacji może prowadzić do licznych błędów, których można uniknąć korzystając z języka statycznego. Za przykład posłuży nam prosta funkcja napisana w JavaScript:
Jak widzisz JavaScript nie ma żadnego problemu z tym, że jeden z argumentów to string
- dokonał niejawnej konwersji, a następnie doszło do konkatenacji stringów, dokładnie tak, jak w przykładach powyżej, nie otrzymaliśmy również żadnego błędu, a sam kod działa poprawnie. Z pewnością nie jest to jednak wynik którego oczekujemy.
Z pomocą przychodzi TypeScript. Napiszemy dokładnie taką samą funkcję, jednak tym razem dodamy do niej statyczne typy. Dzięki temu na bieżąco będziemy widzieć problemy z naszym kodem.
Do parametrów funkcji add
dodaliśmy następujący kod :number
, jeżeli ta składnia wydaje Ci się dziwna i niezrozumiała, nie przejmuj się, poznasz ją dokładnie w kolejnych artykułach. Zapis ten oznacza, że argumentami funkcji add
muszą być zawsze dwie wartości typu number
. W momencie próby przekazania innego typu otrzymujemy błąd już na poziomie kompilacji kodu i jednocześnie unikamy go w czasie działania aplikacji.
Kolejną zaletą jest czytelność naszego kodu (choć w tej kwestii zdania się podzielone. Niektórzy twierdzą, że dodatkowy zapis wymagany przez TypeScript zaciemnia kod i utrudnia jego analizę, ja jednak nie zgadzam się z tym twierdzeniem, kiedy tylko zaznajomisz się z podstawową składnią tego języka, jego odczytanie nie będzie stanowić żadnego problemu.) Już na pierwszy rzut oka widać, że oba parametry muszą mieć typ number
- nie musimy analizować ciała funkcji żeby zrozumieć co dokładnie powinniśmy przekazać jako argumenty.
Jawnie zadeklarowaliśmy także typ, który powinien zostać zwrócony z funkcji, co również zabezpiecza nas przed popełnieniem błędu w przyszłości. Jeżeli kiedyś przyjdzie nam przepisać, zmienić lub usprawnić jej działanie TypeScript zabezpieczy nas przed przypadkową zmianą zwracanego typu.
Już w momencie próby zwrócenia z funkcji innego typu niż number
zobaczymy błąd, informujący nas o popełnionej pomyłce. Oczywiście jest to trywialny przykład, jednak w prawdziwym kodzie funkcje potrafią być znacznie bardziej skomplikowane, a dostrzeżenie błędu bez pomocy TypeScriptu może nie być już tak proste.
Czy warto stosować TypeScript?
Zdecydowanie tak. Głównym argumentem stosowanym przez przeciwników tego rozwiązania jest to, że musimy napisać więcej kodu niż zwykle. Jest to oczywiście prawda, jednak takie rozwiązanie zaprocentuje w przyszłości - projekt staje się znacznie łatwiejszy do utrzymania i wprowadzania zmian, a także znacznie mniej podatny na błędy ludzkie. Rośnie także czytelność kodu i efektywność podczas pracy z nim. Wiele (o ile nie wszystkie) nowoczesnych edytorów kodu zapewnia szerokie wsparcie i liczne podpowiedzi podczas pracy z tym językiem.
Warto wspomnieć także, że TypeScript możesz wykorzystywać równolegle z niemal każdą biblioteką i frameworkiem, więc nie musisz rezygnować ze swoich ulubionych narzędzi. Dla niektórych może być to oczywiste, jednak spotkałem się już z podobnymi obawami.
Dodatkowym faktem przemawiającym na korzyść TSa jest jego popularność. W ankiecie State of JS z roku 2020 ponad 70% ankietowanych używało tego języka i było zadowolonych z jego obecnego stanu. Podobnie sytuacja wygląda na rynku pracy - niemal każda firma tworząca komercyjne aplikacje lub strony internetowe korzysta przy tym z TypeScriptu. Jest to niemal standard w świecie front-endu i nie tylko. Również back-end bardzo często budowany jest w oparciu o tę technologię.
Instalacja
Jest kilka sposobów, żeby zacząć korzystać z TypeScriptu, my skupimy się na dwóch z nich. Pierwszy to instalacja lokalna na komputerze, drugi to korzystanie z przeglądarkowej wersji edytora (ten sposób opisany jest poniżej).
Najprostszym sposobem jest użycie npm
, yarn
lub pnpm
, w tym artykule użyjemy npm
, jeżeli korzystasz z innego menadżera pakietów to zachęcam do zapoznania się z dokumentacją. W tym samym miejscu możemy również przeczytać o dwóch możliwych sposobach instalacji - globalnym (dla wszystkich projektów na komputerze) oraz lokalnym (tylko dla jednego projektu). Którą opcję wybrać?
Instalacja globalna
shell
skopiuj kod
npm install -g typescript
jest przydatna kiedy chcemy mieć możliwość szybkiego sprawdzania jak działa dany kawałek kodu napisany w tym języku, jest to przydatna opcja, kiedy akurat nie pracujemy nad żadnym konkretnym projektem, a jedynie bawimy się kodem i sprawdzamy jego możliwości. Daje możliwość pisania kodu w TS praktycznie od razu, bez żadnych dodatkowych kroków.
Instalacja lokalna
shell
skopiuj kod
npm install typescript --save-dev
to zalecane rozwiązanie dla większości projektów. Dzięki takiemu podejściu mamy pewność, że wszystkie osoby pracujące nad kodem mają tą samą wersję danej paczki, a co za tym idzie, unikamy wielu błędów i problemów z jego kompilacją.
Oczywiście jedna opcja nie wyklucza drugiej. Możemy zainstalować TypeScript globalnie, a w projektach nad którym pracujemy instalować go również lokalnie, dla każdego projektu osobno. Zwróć uwagę, że w tym przypadku używamy flagi --save-dev
, oznacza to, że TS zostanie dodany jako zależność deweloperska i nie będzie widoczny w kodzie produkcyjnym. Jeżeli chciałbyś dowiedzieć się dlaczego tak się dzieje, to zachęcam do przeczytania kolejnego artykułu z tej serii.
To już prawie wszystko. Żeby rozpocząć projekt w TypeScript utwórz folder w którym będziesz pisać kod, a następnie w terminalu (upewnij się, że ścieżka wskazuje na nowo utworzony folder) wykonaj polecenie tsc --init
.
Wygenerowany został plik konfiguracyjny, omówimy go szczegółowo w dalszych artykułach. Jest to zbiór reguł, które zostaną użyte w czasie kompilacji kodu do JavaScriptu.
Ostatni krok to utworzenie pliku o rozszerzeniu .ts, a następnie wykonanie komendy tsc
, która skompiluje kod TS do JS w oparciu o plik tsconfig.json
. Jeżeli w Twoim folderze pojawił się nowy plik z rozszerzeniem .js
, to znaczy, że wykonałeś wszystkie kroki poprawnie i jesteś gotowy do lektury kolejnych artykułów.
Możesz również zajrzeć do dokumentacji żeby poznać wszystkie możliwości kompilatora, jednak na tym etapie nie jest to konieczne.
Alternatywnym sposobem na uruchomienie programu napisanego w TypeScript są polecenia:
npx ts-node nazwaPliku.ts
- kompiluje, a następnie uruchamia kod, z wykorzystaniem Node'a. Oznacza to, że nie zobaczymy efektu działania naszego programu w przeglądarce. Pamiętaj, że ścieżka w terminalu powinna wskazywać na folder, w którym znajduje się plik z kodem. Skrypt ten ma znacznie więcej opcji, a jeśli chcesz o nich poczytać więcej, to zapraszam tutaj.
npx tsx nazwaPliku.ts
- różnica pomiędzy poprzednim skryptem polega w dużej mierze na używanym kompilatorze (ts-node
używa TypeScript compiler, a tsx
Esbuild), choć oczywiście nie jest to jedyna rzecz. Także w tym przypadku możliwości są znacznie większe niż tylko skompilowanie kodu. Dokumentację znajdziesz tutaj.
Warto zaznaczyć, że żadne z powyższych poleceń nie wymaga pliku tsconfig.json
do poprawnego działania. Nadal jednak zalecam stworzenie go, aby móc w przyszłości dostosować konfigurację do własnych potrzeb.
Playground
Alternatywą, dla instalacji TypeScriptu na komputerze, może być oficjalny playground. Jest to miejsce, gdzie możemy "pobawić się" kodem i przetestować jego możliwości. Niezwykle przydatne podczas prototypowania, lub gdy po prostu chcemy coś szybko sprawdzić i nie mamy akurat otworzonego żadnego projektu.
Ta opcja nie wymaga żadnej konfiguracji od użytkownika (choć dopuszcza taką możliwość dając nam dostęp do pliku tsconfig.json
w formie graficznego interface'u. Znajdziesz go w zakładce TS Config) i prawdopodobnie podczas nauki skorzystasz z niej nie raz, dlatego polecam już teraz sprawdzić, jakie możliwości daje. Znajdziesz go tutaj.
Playground z zaznaczonymi najważniejszymi sekcjami
Sekcja pomarańczowa - miejsce na nasz kod.
Sekcja czerwona - podgląd na żywo kodu po skompilowaniu do JavaScriptu (jeżeli zaznaczona jest opcja .JS). Pozwala zobaczyć również inne, nieco bardziej zaawansowane rzeczy, takie jak deklaracje typów, błędy, logi oraz pluginy
Sekcja żółta - ustawienia przydatne podczas pracy z edytorem. Przede wszystkim możemy tu zmienić używaną wersję języka, wykonać nasz kod (wtedy też możemy zobaczyć logi oraz błędy z zakładki czerwonej), wyeksportować, lub po prostu się nim z kimś podzielić.
Oczywiście nie stworzysz tu prawdziwej aplikacji - jeżeli taki masz zamiar, to zachęcam zapoznać się z punktem instalacja.
Co dalej?
Masz już teoretyczne podstawy i wiesz dlaczego warto poznać TypeScript. Nadal jednak nie napisaliśmy ani jednej linii kodu w tym języku. Artykuł ten miał na celu przygotować Cię do dalszej nauki.
Na tym etapie jesteśmy już gotowi do rozpoczęcia praktycznej części, jednak zrobimy to dopiero w kolejnym artykule do którego przeczytania już teraz zachęcam.