Typescript — Microsoft, robicie to dobrze

Wraz ze wzrostem znaczenia języków skryptowych w obszarze Web Developmentu, pojawiła się potrzeba ich udoskonalenia. Podjęto próbę wyeliminowania istniejących niedoskonałości i ułatwienia pracy programistom. Jako bazę przyjęto JavaScript, czyli najchętniej używany skryptowy język programowania, istniejący na rynku od niespełna 8 lat.

Mimo swojej popularności, JavaScript okazał się być wąskim gardłem przy dużych, złożonych projektach. Z tego powodu inżynierowie z Microsoft’u postanowili stworzyć narzędzie, dzięki któremu utrzymanie aplikacji będzie tańsze, prostsze i zdecydowanie bardziej efektywne. W ten sposób w 2012 roku powstał TypeScript - open source’owy język programowania, będący nadzbiorem języka JavaScript.

Co wyróżnia TypeScript?

TypeScript w odróżnieniu od JavaScript’u jest językiem kompilowanym a nie interpretowanym, co pozwala skutecznie wykryć większość błędów jeszcze przed uruchomieniem naszego kodu. Z doświadczenia mogę powiedzieć, że do kompilowania najczęściej używa się transpilatora WebPack wraz z loaderem Babel (babel-preset-typescript). Babel w połączeniu z ts-loader’em kompiluje kod napisany w TypeScript do plików z rozszerzeniem JavaScript oraz transpiluje go na starszy zapis w celu lepszego wsparcia dla większości przeglądarek (Babel w wersji 7 potrafi w pełni zrozumieć i kompilować kod TypeScript, więc nie ma potrzeby używania dodatkowo ts-loader’a do kompilowania kodu). Sam proces kompilowania możemy również ustawić według własnego uznania. Służy do tego m.in. plik tsconfig.json, w którym domyślnie zawierają się podstawowe opcje konfiguracji.

Można zatem powiedzieć, że TypeScript to środowisko wykonawcze JavaScript z dodatkową funkcją sprawdzania typów podczas kompilacji. Z tego wynika, że dowolny, prawidłowy kod napisany w JavaScript jest również prawidłowym kodem w TypeScript. Dzięki temu możemy, stopniowo przekształcać już istniejący kod JavaScript na jego wersję w TypeScript i będzie on działał poprawnie.

Statyczny kontroler typów

Każdy język programowania ma swoje dziwactwa i niespodzianki, a JavaScript nie oszukujmy się, ma ich od groma! Chyba większość osób które interesują się szeroko pojętym front-endem, a szczególnie programowaniem w JS zna tego mema:

W większości języków programowania te “dziwactwa” by nie przeszły, gdyż kompilator wygenerowałby błąd. Natomiast JavaScript nie pyta nas o czym myśleliśmy pisząc taki kod, on po prostu stara się nas zrozumieć. O ile w małych aplikacjach łatwo jest wychwycić tego typu nieprawidłowości i je naprawić, tak w programach zawierających tysiące linijek kodu, błędne zapisy mogą stanowić poważny problem, a ich znalezienie z pewnością zafunduje kilka(naście) siwych włosów na głowie.

W większości języków programowania te “dziwactwa” by nie przeszły, gdyż kompilator wygenerowałby błąd. Natomiast JavaScript nie pyta nas o czym myśleliśmy pisząc taki kod, on po prostu stara się nas zrozumieć. O ile w małych aplikacjach łatwo jest wychwycić tego typu nieprawidłowości i je naprawić, tak w programach zawierających tysiące linijek kodu, błędne zapisy mogą stanowić poważny problem, a ich znalezienie z pewnością zafunduje kilka(naście) siwych włosów na głowie.

I to jest ta scena, w której pojawia się TypeScript wraz z jego statycznym kontrolerem typów. Służy on m.in. do wykrywania błędów w kodzie jeszcze przed jego uruchomieniem, proces ten nosi nazwę - sprawdzanie statyczne. TypeScript dokonuje sprawdzenia na podstawie rodzaju przechowywanych wartości. Dzięki temu posiadamy zawsze pełną informację o ich typach. W połączeniu z silnym typowaniem, które zakłada, że zmienna o ustalonym typie nie może być użyta w miejscu gdzie oczekiwany jest inny typ, jesteśmy w stanie od podstaw tworzyć czytelny i bezpieczny kod. Dodatkowo, w odróżnieniu od takich języków jak Java czy C++, TypeScript został również wyposażony w mechanizm inferencji typów - oznacza to, że możemy przypisywać wartości do zmiennych bez specjalnego informowania programu o typie wartości. Co więcej, program automatycznie sprawdza wartości zwracane w funkcjach i samodzielnie określa ich typ, więc nie musimy robić tego ręcznie w definicji funkcji. Statyczne typowanie pozwala zatem na wyeliminowanie znacznej ilości błędów już na etapie programowania aplikacji. Na pewno znajdą się zwolennicy, którzy będą twierdzić, że dynamiczne typowanie jest lepsze od statycznego, ponieważ pozwala na większą swobodę w tworzonym kodzie. Jednak w przypadku gdy mamy do czynienia z większymi aplikacjami, ta swoboda może ustąpić miejsca chaosowi, przez co nasz kod traci na przejrzystości i spójności.

Podstawowe typy jakie oferuje nam TypeScript to:

  • Boolean
  • Number
  • String
  • Array
  • Tuple
  • Enum
  • Unknown
  • Any
  • Void
  • Null
  • Undefined
  • Never
  • Object

Aby dowiedzieć się co oznaczają poszczególne typy, zachęcamy do zapoznania się z oficjalną dokumentacją.

Różne IDE a wsparcie dla TypeScript

Zdecydowana większość programistów używa zintegrowanych środowisk rozwoju oprogramowania, wyposażonych w rozmaite funkcjonalności ułatwiające pracę, m.in. statyczną analizę kodu źródłowego. Najpopularniejsze z nich to środowiska od firmy JetBrains np. WebStorm oraz Microsoft’owy Visual Studio Code. Spore grono użytkowników ceni sobie również prostotę i możliwości jakie zapewniają Atom, Sublime i Brackets.

Gdy tworzymy aplikację w JavaScript, zdarzają się sytuacje kiedy nawet najlepsze narzędzia do analizy kodu nie spełniają swojej roli, szczególnie gdy pojawia się jakaś niekonsekwencja w logice. Częstym zjawiskiem są również niejednoznaczne podpowiedzi edytora, które nie naprawiają domniemanego błędu, na domiar złego, zawodzą również narzędzia do refaktoryzacji kodu, wprowadzając zmiany nie w tych miejscach, w których byśmy tego oczekiwali. Tutaj wyłania się kolejna przewaga TypeScript’u, mianowicie możliwość wnioskowania kodu przez edytor, która jest tutaj nieporównywalnie większa i zdecydowanie bardziej precyzyjna. Głównie dzięki jawności typów, edytor doskonale wie gdzie dany element się znajduje i za co odpowiada w naszym programie.

Praktyczne zastosowania TypeScript

TypeScript znakomicie sprawdzi się gdy korzystamy z JavaScript’owych framework’ów takich jak Vue, React czy Angular, gdzie szerokie zastosowanie znajdują import i eksport elementów naszego kodu oraz zewnętrznych bibliotek. Analiza kodu będzie nas ostrzegać jeśli spróbujemy wykorzystać funkcjonalność w nieodpowiedni sposób, a także podpowie jak powinniśmy jej używać (wyjątek stanowi typ Any, który jest swego rodzaju furtką do dynamicznego typowania i nie zalecam z niego nadmiernie korzystać). Gdy logika naszej aplikacji jest obszerna i złożona, takie rozwiązanie nie tylko pozwoli na tworzenie prawidłowego kodu, ale również drastycznie ograniczy liczbę potencjalnych komentarzy, które zwykle zawierałyby niezbędne informacje na temat użytych typów.

Częstym sposobem na wykorzystanie TypeScript’u jest również jego użycie po stronie serwera razem z node.js. W sytuacji gdy zarówno front-end jak i back-end aplikacji są tworzone w TypeScript, istnieje możliwość współdzielenia plików pomiędzy tymi warstwami. Dzięki temu możemy uwspólniać fragmenty kodu w obydwu warstwach aplikacji (polimorfizm) oraz korzystać z zalet statycznego typowania. Jest to szczególnie przydatne przy tworzeniu REST API, kiedy dane na temat tego co zwraca endpoint można zapisać do osobnego pliku jako interfejs, a następnie współdzielić go między warstwami. Gdy w jednej z warstw wystąpi niespójność informacji na temat przekazywanych danych, IDE lub kompilator natychmiast nas o tym poinformują. Dzięki takiemu zastosowaniu mamy pewność, że pola obiektu przychodzące z serwera będą całkowicie odpowiadać logice znajdującej się we front-endzie, więc komunikacja pozostanie w 100% spójna.

Jakie korzyści daje nam używanie TypeScript

Tworząc ten artykuł próbowałem znaleźć coś takiego, za co mógłbym się przyczepić do TypeScript’u. Poległem. Tym razem można powiedzieć, że Microsoft rzeczywiście się postarał, zresztą wyniki mówią same za siebie:

  • Airbnb - 38% błędów w kodzie naprawione dzięki statycznemu typowaniu.
  • Slack - ograniczenie ilości błędów podczas konwersji kodu, co doprowadziło do przetłumaczenia całego kodu JavaScript’u na TypeScript już kilka dni od rozpoczęcia konwersji.
  • Google - Od 2015 roku Angular został w pełni przetłumaczony na TypeScript m.in. dzięki lepszej refaktoryzacji.
  • Vue.js - najnowsza wersja framework’a (Vue.js v3) została stworzona w TypeScript, głównie dzięki mechanizmowi statycznego typowania.

TypeScript przyjmuje użyteczności języka z typami statycznymi i przenosi go do ekosystemu JavaScript. Nadal czujemy się tak, jakbyśmy pisali ES6, używamy tej samej standardowej biblioteki, tych samych bibliotek zewnętrznych, idiomów i wielu narzędzi. Skoro tacy giganci zdecydowali się na oparcie swoich projektów o to narzędzie, może rzeczywiście warto zastanowić się nad wdrożeniem go w swoich projektach?

W Webalize uwielbiamy dzielić się swoją wiedzą i wymieniać najlepszymi praktykami, dlatego jeśli masz jakieś pytania lub zwyczajnie chciałbyś porozmawiać o digitalizacji Twojej firmy, koniecznie daj nam znać!