Rozszerzanie modułów TypeScript i obsługa zagnieżdżonych plików JavaScript
Poznaj podstawy rozszerzania modułów w TypeScript oraz jak dodawać definicje typów dla zagnieżdżonych plików JavaScript.
TypeScript od ponad dekady jest cennym dodatkiem do ekosystemu JavaScript, zyskując popularność dzięki możliwości zapewnienia bezpieczeństwa typów dla kodu JavaScript.
Typy dla paczek JavaScript
Dla zachowania zgodności wstecznej i elastyczności, TypeScript umożliwia autorom paczek dostarczanie definicji typów dla ich paczek JavaScript. Definicje tych typów są zazwyczaj przechowywane w repozytorium "DefinitelyTyped". Można zainstalować te definicje typów za pomocą przestrzeni nazw @types
, na przykład @types/react
to definicja typów dla paczki React.
Po zainstalowaniu tych definicji typów można korzystać z paczki z pewnością bezpieczeństwa typów. Oto przykład definiowania komponentu React z bezpieczeństwem typów:
Rozszerzanie modułów
Podczas gdy większość popularnych paczek JavaScript ma dostępne definicje typów w przestrzeni @types
, niektóre paczki mogą nie mieć definicji typów lub mają ich przestarzałe wersje. W takich przypadkach TypeScript oferuje potężną funkcję znaną jako "rozszerzanie modułów", która pozwala na dodawanie definicji typów dla tych paczek. Spójrzmy na przykład:
Teraz możesz użyć tej rozszerzonej definicji typu w swoim kodzie:
Rozszerzanie modułów pozwala nie tylko dodawać definicje typów dla paczek, ale także rozszerzać istniejące definicje typów. Na przykład, można dodać nowe właściwości do obiektu window
:
I użyć tego w swoim kodzie:
W poprzednim wpisie omawialiśmy problem typów w bibliotece React Router i musieliśmy przezwyciężyć wpływ tego problemu rozszerzając i modyfikując istniejący typ poprzez plik deklaracji niestandardowych.
Pamiętaj, że korzystając z rozszerzania modułów, ważne jest dokładne sprawdzenie dokładności definicji typów poprzez dokładną analizę kodu źródłowego JavaScript. Niepoprawne definicje typów mogą prowadzić do błędów w czasie wykonywania. W powyższym przykładzie, właściwość window.foo
musi być typu string, który istnieje na obiekcie window
.
Rozszerzanie globalne
Czasami można napotkać skrypty, które wprowadzają globalne zmienne i może być konieczne dostarczenie definicji typów dla tych zmiennych globalnych, aby móc ich używać w kodzie TypeScript. Na przykład, jeśli masz skrypt, który ustawia globalną zmienną o nazwie __DEV__
:
Możesz dodać definicje typów dla tej globalnej zmiennej w następujący sposób:
Teraz możesz jej używać w swoim kodzie TypeScript:
Łącząc rozszerzanie modułów i rozszerzanie globalne, można nawet rozszerzać definicje typów dla prototypów JavaScript, jednak ogólnie nie jest to zalecane, ponieważ może zanieczyszczać przestrzeń globalną.
Moc rozszerzania modułów pozwala na takie rozszerzenia, ale używaj ich ostrożnie, aby zapobiec zanieczyszczeniu przestrzeni globalnej.
Zagnieżdżone pliki JavaScript
W poprzednich przykładach zakładaliśmy, że importy mogą być rozwiązane za pomocą pliku wejściowego paczki. Jednak niektóre paczki eksportują zagnieżdżone pliki JavaScript bez odpowiednich definicji typów. Rozważmy paczkę o nazwie foo
z następującą strukturą:
Paczka foo
eksportuje plik index.js
jako punkt wejścia, a także eksportuje katalog bar
.
Aby rozszerzyć definicje typów dla paczki foo
, można utworzyć plik foo.d.ts
:
Jednak gdy próbujesz zaimportować plik baz.js
w TypeScript, napotkasz błąd:
Aby rozszerzyć definicje typów dla pliku baz.js
, musisz utworzyć osobny plik baz.d.ts
:
To zapewnia, że TypeScript może zlokalizować moduł i jego powiązane definicje typów:
Aby utrzymać zorganizowane definicje typów, można odwzorować strukturę paczki w swoich plikach z definicjami typów:
To podejście utrzymuje kod TypeScript zorganizowany i bezpieczny pod względem typów, nawet podczas pracy z zagnieżdżonymi plikami JavaScript.