Читать книгу Programowanie w TypeScript - Boris Cherny - Страница 7
ОглавлениеROZDZIAŁ 1
Czyli zdecydowałeś się kupić książkę o TypeScripcie. Dlaczego?
Być może masz już dość dziwnych błędów JavaScriptu typu cannot read property coś tam coś tam undefined. A może słyszałeś, że TypeScript podnosi skalowalność kodu i chciałeś sprawdzić, o co tyle szumu? Może jesteś programistą C# i zastanawiasz się, czy nie spróbować całego tego JavaScriptu. A może jesteś programistą języka funkcyjnego i zdecydowałeś, że nadszedł czas wrzucić wyższy bieg. Może twój szef ma już tak dość problemów produkcyjnych powodowanych przez twój kod, że dał ci tę książkę pod choinkę (powiedz stop, gdy będziemy na dobrym tropie).
Niezależnie od osobistych przyczyn, to prawda, co mówią o języku TypeScript – naprawdę znajdzie on zastosowanie w nowej generacji aplikacji sieci Web, aplikacji mobilnych i Internetu rzeczy (Internet of Things – IoT). Zwiększy on bezpieczeństwo programów, będzie pełnił funkcję dokumentacji dla nas i przyszłych programistów, ułatwi przeprowadzanie refaktoryzacji i sprawi, że połowa naszych testów jednostkowych stanie się niepotrzebna („Jakie testy jednostkowe?”). Dzięki TypeScript podwoi się twoja produktywność w pracy, a przy odrobinie szczęścia uda ci się wyciągnąć szczęśliwy los na loterii w prima aprilis.
Ale najpierw pozwól nam wyjaśnić, co mamy na myśli, mówiąc o „bezpieczeństwie”. Oczywiście chodzi nam o bezpieczeństwo typów.
Bezpieczeństwo typów
Wykorzystywanie typów do powstrzymywania programów przed podejmowaniem nieprawidłowych akcji1.
Oto kilka przykładów nieprawidłowych akcji:
mnożenie liczby i listy,
wywoływanie funkcji na liście łańcuchów, mimo że tak naprawdę potrzebuje ona listy obiektów,
wywoływanie metody na obiekcie, który w rzeczywistości nie ma tej metody,
importowanie modułu, który został usunięty.
Niektóre języki programowania próbują, jak najlepiej potrafią, radzić sobie z tego typu błędami. Próbują domyślić się, do czego miała prowadzić nieprawidłowa akcja, ponieważ każdy robi, co może, prawda? Weźmy pod uwagę następujący kod JavaScriptu:
3 + [] // Otrzymujemy łańcuch “3”
let obj={}
obj.foo // Otrzymujemy undefined
function a(b) {
return b/2
}
a(“z”) // Otrzymujemy NaN
Jak widać, zamiast zgłaszać wyjątek w odpowiedzi na próbę wykonania nieprawidłowej akcji, JavaScript próbuje zaradzić sytuacji i unikać wyjątków, gdy jest to możliwe. Czy JavaScript chce pomóc? Na pewno. Czy ułatwia szybkie zidentyfikowanie błędów? Raczej nie.
A teraz wyobraźmy sobie, że JavaScript zgłasza więcej wyjątków, zamiast po cichu radzić sobie ze stworzoną przez nas sytuacją. Moglibyśmy otrzymać następujące informacje zwrotne:
3 + [] // Błąd: Czy naprawdę chcesz dodać liczbę i tablicę?
let obj={}
obj.foo // Błąd: Zapomniałeś zdefiniować w obj właściwość “foo”.
function a(b) {
return b/2
}
a(“z”) // Błąd: Funkcja “a” oczekuje liczby,
// a przekazałeś łańcuch.
Proszę nas źle nie zrozumieć: gotowość do rozwiązywania naszych błędów to kapitalna cecha języka programowania (gdyby było to możliwe nie tylko w przypadku programów). W JavaScript ta funkcja oddala jednak moment popełnienia błędu w kodzie od momentu dowiadywania się o tym, że popełniliśmy błąd w kodzie. A to często oznacza, że o naszym błędzie dowiadujemy się dopiero od innych osób.
W związku z tym pojawia się pytanie, kiedy dokładnie JavaScript informuje nas, że popełniliśmy błąd.
Odpowiedź brzmi: po uruchomieniu programu. Program może zostać uruchomiony, gdy testujemy go w przeglądarce lub gdy użytkownik odwiedzi naszą stronę, lub gdy wykonamy test jednostkowy. Zdyscyplinowani programiści, którzy piszą dużo testów jednostkowych i e2e (end-to-end), wykonują testy dymne przed wypchnięciem kodu i testują go lokalnie przed przekazaniem do użytkowników, zazwyczaj dowiadują się o swoich błędach przed użytkownikami. Ale co z resztą programistów?
Tu z pomocą przychodzi TypeScript. Jego dużą zaletą jest nie tylko dostarczanie pomocnych komunikatów o błędach, lecz także moment ich przekazywania: TypeScript pokazuje komunikaty o błędach w edytorze tekstowym w czasie wpisywania kodu. To oznacza, że nie musimy polegać na tym, że tego typu błędy zostaną wykryte przez testy jednostkowe, testy dymne lub naszych współpracowników: TypeScript wykrywa te błędy i informuje nas o nich podczas pisania programu. Zobaczmy, co TypeScript mówi o naszym poprzednim przykładzie:
3 + [] // Błąd TS2365: Nie można zastosować operatora ‘+’ do typów ‘3’
// i ‘never[]’.
let obj = {}
obj.foo // Błąd TS2339: Właściwość ‘foo’ nie istnieje w typie ‘{}’.
function a(b: number) {
return b/2
}
a(“z”) // Błąd TS2345: Nie można przypisać argumentu typu ‘”z”’
// do parametru typu’number’.
Nie tylko eliminuje on całe klasy błędów związanych z typami, ale tak naprawdę zmienia sposób pisania kodu. W efekcie zaczynamy od naszkicowania programu na poziomie typów, a dopiero później wypełniamy go na poziomie wartości2 – przypadki brzegowe bierzemy pod uwagę już w fazie projektowania i tworzymy programy, które są prostsze, szybsze, bardziej zrozumiałe i łatwiejsze w utrzymywaniu.
Gotowy do rozpoczęcia przygody? W takim razie wyruszamy!