Dlaczego warto używać TypeScripta?

TypeScript istnieje na rynku już ładnych parę lat, jednak to w ostatnich dwóch latach zyskał największą popularność. Nie ma się czemu dziwić, bo TS wprowadza wiele zalet do pisania kodu opartym na czystym Javascripcie.

Co to jest TypeScript?

Jestem niemal pewien, że wiesz, co to TypeScript i na jakim problemie się skupia. Słowem wstępu wypadałoby jednak wspomnieć trochę o teorii. Głównym zadaniem TS, jak sama jego nazwa wskazuje, jest wprowadzenie typowania do kodu Javascript. Vanilla JS nie daje nam takiej możliwości. Tam typowanie jest bardzo znikome, co bardzo często skutkuje nieoczekiwanymi, trudnymi do zdebugowania błędami. Ponadto, wprowadza nowe konstrukcje i mechanizmy niekiedy dostępne w innych, silnie typowanych językach, a o których sobie dziś po części wspomnimy. Tutaj muszę zaznaczyć jedną rzecz: TypeScript to nie jest język programowania z prawdziwego zdarzenia. Jest to tak naprawdę type checker, nadzbiór języka JavaScript, który wprowadza nowe mechanizmy. TypeScript kompiluje się do JSa, a to oznacza, że każdy kod vanilla JS w teorii zadziała w TSie. Przeglądarki czy silniki nie czytają kodu TS, tylko JS. Ktoś więc mógłby spytać, po co w ogóle nam TypeScript skoro jego kod możemy skompilować używając stary, nieotypowany JS. I tutaj przechodzimy do oprogramowania, które wspiera pisanie kodu w TypeScripcie. Zanim się rozwinę na ten temat, chciałbym zastrzec, że nie jest to żaden tutorial, a jedynie moje luźne myśli po dwóch miesiącach pracy w TypeScripcie. Przez ten okres zdążyłem już wyciągnąć pozytywne wnioski idące z używania tej technologii i dziś chciałbym, aby ktoś dostrzegł mój punkt widzenia. Miej zatem moje słowa na dystans, mimo że zawsze przykładam się, by przekazywać tylko najrzetelniejszą wiedzę.

Działanie TSa w praktyce

Wspomniałem przed chwilą, że TS to type checker. Oznacza to tyle, że całą swoją robotę robi podczas pisania kodu i sprawdzaniu, czy my jako programiści piszemy kod w taki sposób, jak TS sobie tego życzy. Kojarzycie ESLinta, stróża prawa dobrych praktyk pisania kodu w JS? Podobnie jak ESLint, TS podczas developmentu (a nie kompilowania) sprawdza kod programisty i "lintuje", czyli podpowiada, czy gdzieś przypadkowo (lub umyślnie) nie popełniliśmy błędu z typami i wyświetla nam dokładne miejsce, gdzie to się wydarzyło, dodatkowo podpowiadając, co jest nie tak. Dodatkowo możemy tak skonfigurować projekt za pomocą zasad, by podczas reloadingu nie budował aplikacji (wyświetli wtedy te same błędy, co w edytorze przy reloadingu) albo nawet nie przepuszczał commitów ze zmianami, w których to błędy występują (do tego służy na przykład lint-staged i/lub husky). I to jest w zasadzie cała istota działania TypeScripta. Nasuwa ci się być może teraz pytanie, jaki edytor kodu będzie to TS najlepszy? Nie wiem jak z innymi edytorami, ale wiem, że VSCode i WebStorm natywnie wspierają ten język i nie trzeba posługiwać się w nich dodatkowymi pluginami.

Cena używania TSa

Podobnie jak przy każdym narzędziu, czy technologii, potencjalnie wprowadzającej bardzo dobre rzeczy do projektu lub pisania kodu w ogóle, używanie TypeScripta nie jest pozbawione tradeoffów (kompromisów, czyli coś za coś). Za ogół zalet wynikających z TSa musimy zapłacić niemałą cenę. Po pierwsze, jest to czas spędzony na naukę nowej technologii. Nie oszukujmy się: to nie jest jedna mała libka zaciągnięta z npma, tylko moloch wprowadzający nowy poziom abstrakcjonizmu w kontekście pisaniu kodu. Sam handbook od Microsoftu (twórca TSa) to pewnie kilkaset stron czystej teorii. Ponadto, jest to rozszerzenie vanilla JS, więc jasne jest, że nigdy nie będzie tak szeroko używany, jak stary żółty JS. Oznacza to, że wiele bibliotek i narzędzi pisanych przez programistów będzie pozbawione typów, a to z kolei wyklucza nas z korzystania w pełni z możliwości TS. Co prawda, możemy używać dependencji bez zdefiniowanych dla niego typów, ale psujemy tym potencjał i spójność projektu. Na szczęście TS staje się coraz popularniejszy i programiści widzą w nim coraz więcej korzyści, dodając do swoich istniejących bibliotek moduły z typami. Trzeba mieć jednak powyższe na uwadze. Na pewno nie ma się tym co przejmować i nie jest to powód, dlaczego nie powinniśmy używać TSa - najpopularniejsze bilbioteki go wspierają. Kolejnym tradeoffem jest więcej czasu spędzonego przy pisaniu kodu. Na napisanie tej samej aplikacji w TS i JS, dłużej nam zejdzie, robiąc to w tym pierwszym. Korzyści z tego są jednak wymierne i za chwilę przejdę, by powiedzieć dlaczego. Nie będę jednak się tu skupiał na aspektach technicznych i pisaniu stricte kodu. Jest to czysto merytoryczny wpis.

Więcej typów = mniej błędów

Kiedyś, na początku mojej drogi z programowaniem, kiedy jeszcze uczyłem się C++, bardzo spodobało mi się to, że JavaScript dynamicznie przypisuje typy do zmiennych i jego użytkownik nie musi się przejmować jakimiś przedrostkami. Myślałem, że to zaleta, a nie ujma. Po wejściu w świat  webdevelopmentu zrozumiałem, jak bardzo się myliłem. W odmętach javascriptowego kodu przekonałem się, że o poprawne przekazywanie danych muszę dbać sam, a szczególnie dobitnie to odczułem podczas pracy w Reakcie: niejednokrotnie debugowany błąd spowodowany tym, że dostaje wartość undefined. Kto się z tym nie spotkał, niech pierwszy rzuci kamieniem. Podczas używania TypeScripta nie ma możliwości, żeby w aplikacji nieoczekiwanie wyskoczył ci NaN lub undefined, bo się pomylisz. Nie wyślesz do komponentu propsa lub wartości tego propsa, którego nie zdefiniowałeś w interfejsie lub typie. Nie wyślesz i nie otrzymasz wartości, której po prostu wcześniej nie określiłeś. I edytor lub runtime cię o tym powiadomi. Nie muszę chyba tłumaczyć, ilu potencjalnym błędom wynikającym z używania i parsowania danych, TypeScript zapobiega.

Kojarzysz dodatkową bilbiotekę do Reacta o nazwie propTypes? Służy ona do imitacji typowania w wysyłanych propsach do komponentu w Reakcie. Zapomnij o niej. Od teraz robisz do by default w TSie. Walidacja poprawności danych w testach? Nigdy w życiu. Po co to robić skoro TS ogarnie to za ciebie. I, mimo że brzmi to jak chamska reklama produktu w tv, to nie jest to wyssana z palca bzdura. Ale jak już wspomniałem, musisz za to zapłacić cenę.

Wysoka wartość długoterminowa i zwrot ceny

Wspomniałem, że pisanie kodu w TS trwa dłużej. To prawda. Długoterminowo jednak najpewniej ci się to zwróci. Prawdopodobnie tak skonfigurujesz sobie projekt, że twój developer experience, w porównaniu do JS, zwiększy się diametralnie. Wypracujesz wzorce i będziesz ich używał. Zamkniesz się w bezpiecznej, wysoce skalowalnej, abstrakcyjnej kuli danego projektu i będziesz go respektował nie tylko, jak wielki TypeScript nakazał, ale sam znajdziesz dla siebie i dla projektu najlepsze rozwiązania. Nie wspominając już, jak dużo się nauczysz. O jakim developer experience mówię? Pokażę ci to na przykładzie.

Powiedzmy, że tworzymy komponent buttona, który będzie przyjmował 3 warianty i w zależności od wariantu, będzie inaczej wyglądał/zwracał inny JSX/robił co innego. To jest nieistotne. Istotne jest natomiast to, w jaki sposób zdefiniujemy sobie typ propsa variant. A możemy zrobić to na przykład tak:

type ButtonVariant = 'primary' | 'secondary' | 'tertiary';

interface ButtonProps {
  variant: ButtonVariant;
}

const Button: FC<ButtonProps> = ({ variant }) => {
  if (variant === 'primary') return <button type="button" />;
  if (variant === 'secondary') return <button type="submit" />;
  return <button />;
};

W ten sposób zdefiniowaliśmy, że props może przyjmować tylko trzy wartości stringowe: primary, secondary i tertiary. Dzięki temu, kiedy będziemy chcieli przypisać do propsa jakąś inną wartość, TypeScript to szybko wychwyci i potraktuje jako błąd. Dodatkowo, podczas użycia komponentu w kodzie, edytor podpowie, jakie wartości możemy do propsa przypisać.

zdjęcie tematyczne
VSCode podpowiada mi, jaką wartość mogę przypisać do propsa

Jest to tylko jedno z wielu usprawnień w pisaniu kodu w TypeScripcie, a pokazałem chyba najprostsze. Dzięki TypeScriptowi ułatwimy również start nowym osobom w projekcie i usprawnimy sobie powrót do niego po długim czasie. Jest to możliwe w dużej mierze dzięki czytaniu typów i poznawaniu tym samym kontekstu kodu, czy też aplikacji.

Twój kod wkroczy na wyższy poziom

Generalnie ze swoich spostrzeżeń widzę, że pisanie typescriptowego kodu jest jakby bardziej spójne, wszystko się tam klei do kupy i ładnie się na to patrzy. Na początku, kiedy wkroczysz w TypeScripta, będzie chaos, w którym będziesz musiał się odnaleźć (jeśli chcesz poczytać więcej o chaosie, przejdź tutaj). Spokojnie, to normalne. Z czasem odczujesz, że idziesz w dobrym kierunku i wszystko stanie się jasne i klarowne. Takie jest też de facto zadanie TypeScripta. Szczególnie będzie tak podczas pracy w projekcie, gdzie wzorce są wypracowane wspólnie, zespołowo. Moim zdaniem w czystym JSie też da się napisać ładny, spójny kod. Jest to jednak trudniejsze. Ten akapit jest najbardziej subiektywny z całego artykułu, dlatego nie traktuj moich słów jako wyrocznię. Sam znajdź własne wnioski.

TypeScript is love, Typescript is life?

Niekoniecznie. Bzdurą by było stwierdzenie, że TSa powinno się używać zawsze i wszędzie. Moim zdaniem jest co najmniej kilka przypadków, kiedy nie warto go stosować:

  • projekt jest na tyle mały, że TypeScript byłby w nim armatą na muchy. W programowaniu ważne jest, by dostosowywać dostępne technologie i narzędzia do potrzeb projektowych. Wyjątkiem jest tutaj mały projekt na TypeScripcie, służący do jego nauki,
  • dopiero zaczęliśmy uczyć się javascriptu lub umiemy jego totalne podstawy. Według mnie to nie jest dobry czas na naukę TSa. Warto wtedy poczekać i poduczyć się vanilli. TypeScript na tyle zmienia podejście do pisania kodu, że w momencie, kiedy natrafimy na kod czysto javascriptowy, nie odnajdziemy się w nim. Pamiętaj, po nitce do kłębka. Mimo wszystko chciałbym poznać kiedyś programistę, który zaczął od nauki od TSa i poznać jego zdanie,
  • zależy nam na czasie/szybkiej wersji MVP. Wspomniałem wcześniej, że używanie TSa zwiększa nakład pracy. Pamiętaj, że czas to pieniądz i to za to klient zazwyczaj zapłaci. Kiedy goni nas czas, może warto poczekać i w późniejszym czasie zastanowić się na przepisanie kodu do TypeScripta.

W każdym innym wypadku rozważałbym pisanie kodu w TypeScripcie, a w szczególności kiedy:

  • tworzymy rozbudowany projekt,
  • piszemy bilbliotekę, z której inni programiści mogą skorzystać,
  • zależy nam na jakości i jak najmniejszej ilości potencjalnych błędów w aplikacji.

Podsumowanie

Nauka TypeScripta nie jest różami usłana. Często popadniemy we frustrację i chaos, któremu będzie trzeba sprostać. Cena za naukę jest duża. Korzyści mogą być jednak jeszcze większe. TypeScript to język który, rozwiązuje bardzo dużo problemów JavaScriptu. Dzięki niemu zwiększymy developer experience, sprawimy, że kod stanie się prostszy do przyswojenia, zarówno po powrocie do niego po czasie, jak i dla nowych developerów w zespole. Używając typów sprostamy głupim, nieraz trudnym do zdebugowania, błędom i zwiększymy abstrakcyjność pisanego kodu. Jest to technologia, która rozwija się niesamowicie i zyskuje coraz większą popularność. Za kilka lat każda poważna firma będzie używać w swoim stacku TypeScripta. Jest to dodatkowy argument, żeby się go nauczyć.

© Damian Kalka 2021
Wszelkie prawa zastrzeżone