TypeScript – pierwsze kroki. Moduły w TypeScript. Część pierwsza.

W ostatnim wpisie przedstawiłem temat przestrzeni nazw w TypeScript. Jednak prawda jest jednak taka, że przestrzenie nazw używane są rzadko. Dużo częściej korzysta się z mechanizmu modułów.

W dzisiejszym poście pokaże jak stawiać pierwsze kroki właśnie w świecie modułów TypeScript. Zapraszam do lektury.

Moduły w typescript

Zanim przejdę do sedna sprawy, muszę zaznaczyć, że temat modułów w TypeScripcie jest dość szeroki. W dzisiejszym webowym świecie nie ma jednego sposoby na modularyzacje kodu. Wręcz przeciwnie, jest ich mnóstwo! Postaram się omówić te aspekty, które są relewantne dla TS’a, od podstawowych, do tych bardziej zaawansowanych. Warto znać każde możliwe podejście, niezależnie od tego, które jest lepsze, bo nigdy nie wiadomo na jaki kod trafimy 🙂 .

Na początek przedstawię setup dzisiejszego przykładu, bo chcę zacząć mocno praktycznie. Tworzę mały projekt, zawierający typowy dokument HTML: index.html, oraz trzy pliki TypeScriptowe: main.ts, dogs.ts oraz cats.ts. Zawartość tych plików pokażę za chwilę, najpierw muszę omówić konfigurację, która znajduje się wewnątrz tsconfig.js:

Jak widać jest on bardzo prosty. Pierwsze dwie opcje wewnątrz obiektu compilerOptions nie będą miały dziś znaczenia. Ważna jest ta ostatnia czyli outFile. Spowoduje ona, że kompilowany kod trafi do jednego pliku – build.js.

Dodatkowo w konfiguracji ustawiam automatyczną kompilację projektu przy zapisywaniu.

Treści dokumentu HTML nie będę przedstawiał, jest ona tak podstawowa jaka tylko może być. Trzeba tylko pamiętać o dodaniu do niej skryptu build.js.

Plik main.js to mój plik wejściowy i jego treść omówię na końcu. Najpierw pokaże zawartość moich dwóch modułów dogs.ts oraz cats.ts. Tak jest, modułów. W TypeScript każdy plik to już osobny moduł. Wszystko zależy od tego jak dodamy go do projektu 😉 .

Oto treść plików:

Nic specjalnego, nawet nie ma tu żadnego kodu TSowego, ale to nie ma znaczenia. Te dwa moduły zawierają metody, które chciałbym wykorzystać w moim głównym programie. Najprostszym sposobem na dołączenie ich do projektu jest kompilacja na JS i dodanie odpowiednich elementów script do dokumentu HTML. Jest to zarazem najsłabsze rozwiązanie 🙂 nadające się może na początku projektu. Nie muszę chyba pisać o tym, że mnogość tagów script w projekcie jest mało wydajna (tak, wiem że sam tak robię w mojej grze październikowej, ale dopiero się uczę TSa, teraz będę już wiedział 😉 )

Lepszym sposobem na to będzie użycie specjalnej TSowej opcji, referencji modułów. Zrobię to teraz w moim głównym pliku:

Na samej górze mojego pliku main.ts dodałem specjalny „tag” poprzedzony trzema ukośnikami. Wewnątrz tagu do atrybut reference path przypisuję ścieżkę do pliku z modułem, który chcę wykorzystać. W rezultacie, podczas kompilacji, tagi referencji zostaną zamienione na treść pliku. Jeśli zapiszę teraz projekt, otrzymam plik build.js, którego treść wygląda tak:

Naprawdę nieźle! Moje moduły zostały bardzo ładnie zbundlowane i wszystko działa jak trzeba. Po uruchomieniu aplikacja wypisuje odpowiednie wiadomości do konsoli. Niestety jest jeden minus. Treści modułów zostały przypisane do globalnego zakresu.

Na szczęście sposób aby sobie z tym poradzić jest bardzo prosty. Niektórzy mogliby powiedzieć, że tak naprawdę dopiero teraz mój kod zawierać będzie moduły, ale tak jak pisałem wcześniej już o samym pliku należy myśleć jako o module 😉 . Ok, do plików dogs.ts oraz cats.ts wprowadzam następujące zmiany:

Użyłem tutaj operatora module. Podaje mu nazwę modułu jaki chcę uzyskać i parę nawiasów klamrowych. Wewnątrz nawiasów wrzucam treść plików. Tak zapisany moduł jest ‚zamknięty’ i jeśli chcę aby jakiś jego element był dostępny, muszę dopisać przy nim operator export, podobnie jak w przestrzeniach nazw. Jak widać eksportuję funkcje z oby modułów.

Aby kod zadziałał należy zmienić jeszcze wywołania funkcji w pliku main.js. Od teraz muszę odnosić się do nich przez nazwy, które przypisałem do modułów:

Dlaczego tak to wygląda? Odpowiedź leży wewnątrz pliku build.js:

Jak widać TS po prostu za pomocą samowywołujących się funkcji tworzy obiekty z własnym scopem, czyli klasyczny JavaScript. Te elementy, które oznaczyłem operatorem export zwracane są na zewnątrz. Gdyby w modułach istniały fragmenty kodu, które nie byłby eksportowane, nie byłby one zwracane, czyli stałby się ‚prywatne’.

Ten system modułów działa naprawdę przyzwoicie. Przy niewielkich projektach, które pisałbym sam, pomyślałbym o użyciu właśnie tego podejścia. Problemy pojawiają się w momencie kiedy do projekty chcemy dodać moduły zewnętrzne. A jak wiadomo z taką sytuacją w JSie spotykamy się bardzo często. W kolejnym poście opiszę trochę inne podejście do modułów w TypeScripcie, które przy okazji bardzo elegancko pozwalają zarządzać zewnętrznymi plikami. Chodzi mi tu o module loader’y.

Ale na dziś to jednak wszystko. Jeżeli chcesz być na bieżąco z postami na blogu zachęcam do polubienia mojej strony na facebooku. Zawsze zamieszczam tam informacje o wszystkich nowościach. Jest to też dobre miejsce na kontakt ze mną. Na wszystkie pytania zawsze odpowiem :).

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *