TypeScript vs JavaScript: co się zmienia, co generuje tsc | We.Inc
Zobacz TypeScript obok JavaScriptu, do którego się kompiluje, dowiedz się, co wyłapuje type checker, dlaczego typy znikają w runtime i kiedy zwykły JavaScript w zupełności wystarczy.
TypeScript to JavaScript z systemem typów. Piszesz zwykły JavaScript z opcjonalnymi adnotacjami typów, a kompilator tsc je sprawdza, po czym usuwa, tworząc czysty JavaScript. Przeglądarki i Node uruchamiają ten wynik, więc typy nigdy nie istnieją w runtime. Zyskiem jest wyłapywanie błędów podczas edycji, a nie szybszy kod.
Obok siebie
Pytanie
JavaScript
TypeScript
Działa bezpośrednio w przeglądarce?
Tak
Nie, najpierw jest kompilowany lub oczyszczany do JavaScriptu
Kiedy wykrywane są błędy typów?
Podczas działania kodu
Podczas edycji i przy sprawdzaniu przez tsc
Rozszerzenia plików
.js, .mjs, .jsx
.ts, .tsx (.d.ts dla deklaracji)
Typy w runtime
Tylko wartości
Brak, adnotacje są usuwane
Potrzebny krok build?
Opcjonalny
Tak do sprawdzania; do uruchomienia narzędzie usuwające typy lub bundler
Poprawny JavaScript jest poprawnym wejściem?
Tak
Tak, choć checker może zgłaszać błędy
Wybierz przykład poniżej, aby zobaczyć plik TypeScript obok JavaScriptu, który tsc dla niego napisał. Najczęściej wynik to Twój kod z usuniętymi adnotacjami. Kilka funkcji, takich jak enumy, generuje prawdziwy kod, a ta różnica ma znaczenie przy wyborze narzędzi.
Przeczytaj źródło TypeScript po lewej i wygenerowany JavaScript po prawej.
Sprawdź notatkę pod każdą parą, aby zobaczyć, co kompilator sprawdził i co przetrwało w wyniku.
Skopiuj dowolną stronę, aby wypróbować ją we własnym projekcie.
Dodaj tsconfig.json z strict ustawionym na true od pierwszego dnia. Włączenie go później w dużym kodzie ujawni setki błędów naraz.
Podczas migracji zmieniaj nazwę jednego pliku .js na .ts naraz. Ustawienie allowJs pozwala obu rodzajom plików żyć w tym samym projekcie w trakcie przenosin.
Pamiętaj, że JSON z serwera nie ma typów, dopóki go nie sprawdzisz. Adnotacja typu na pobranych danych to obietnica dla kompilatora, a nie sprawdzenie w runtime.
Do uruchamiania kodu używaj szybkiego narzędzia usuwającego typy (Vite, esbuild lub type stripping w Node), a tsc --noEmit trzymaj jako osobne sprawdzenie w edytorze i CI.
Najczęściej zadawane pytania
Czy TypeScript to inny język niż JavaScript?
To nadzbiór. Każdy program TypeScript staje się JavaScriptem, a TypeScript dodaje składnię do opisywania kształtów wartości. Najpierw naucz się JavaScriptu; typy leżą na nim, a nie go zastępują.
Czy TypeScript przyspiesza moją stronę?
Nie. Adnotacje są usuwane przed uruchomieniem kodu, więc przeglądarka wykonuje ten sam JavaScript, który napisałbyś ręcznie. Korzyści to mniej błędów docierających do użytkowników i bezpieczniejszy refaktoring.
Czy tsc odmówi buildu, gdy jest błąd typu?
Domyślnie nie. tsc zgłasza błąd i mimo to zapisuje plik .js, co umożliwia stopniową migrację. Ustaw noEmitOnError, jeśli chcesz, aby nieudane sprawdzenie blokowało wynik.
Czy Node może uruchamiać pliki .ts bez kroku build?
Nowe wersje Node usuwają usuwalną składnię typów i uruchamiają plik, z type stripping włączonym domyślnie od v23.6.0 i v22.18.0. Node nie sprawdza typów, a składnia wymagająca wygenerowanego kodu, na przykład enumy, jest odrzucana.
Kiedy zwykły JavaScript jest lepszym wyborem?
Małe skrypty, szybkie prototypy i strony z kilkoma linijkami interaktywności rzadko zwracają koszt konfiguracji. Gdy projekt ma kilka plików, kilka osób lub dane przekazywane między modułami, checker zaczyna oszczędzać prawdziwy czas.
Co właściwie robi tsc
Kompilator ma dwa zadania, które ludzie często mylą. Po pierwsze sprawdza typy: czyta każdy plik, ustala typ każdej wartości i zgłasza wszystko, co nie pasuje. Po drugie generuje wynik: zapisuje JavaScript bez składni typów i, jeśli o to poprosisz, przepisuje nowszą składnię dla starszych środowisk.
Nowoczesne zestawy narzędzi zwykle rozdzielają te zadania. Bundler taki jak Vite szybko usuwa typy, niczego nie sprawdzając, a tsc --noEmit wykonuje pełne sprawdzenie osobno w edytorze lub CI. Jeśli uruchamiasz tylko bundler, błędy typów mogą trafić na produkcję.
Typy są usuwane, więc waliduj prawdziwe dane
Ponieważ adnotacje znikają, TypeScript nie powstrzyma serwera przed wysłaniem stringa tam, gdzie zadeklarowałeś liczbę. Zapis const user: User = await res.json() mówi checkerowi tylko, żeby Ci zaufał.
Na granicach programu, takich jak dane z formularzy, odpowiedzi fetch i local storage, sprawdzaj wartość w runtime małą funkcją strażnikiem lub biblioteką schematów i pozwól checkerowi nieść tę gwarancję dalej do środka.
Funkcje, które nie są po prostu usuwane
Enumy, namespace z kodem, parameter properties i aliasy import = generują własny JavaScript. TypeScript 5.8 dodał opcję erasableSyntaxOnly, która zgłasza dla nich błąd, dzięki czemu plik działa z narzędziami, które tylko usuwają adnotacje.
Jeśli planujesz uruchamiać pliki .ts bezpośrednio w Node lub przez inne narzędzie usuwające typy, wybieraj unie literałów stringowych i obiekty as const zamiast enumów. Przewodnik po enumach na tej stronie pokazuje oba podejścia obok siebie.
Dodaj TypeScript do projektu JavaScript
Zainstaluj i utwórz tsconfig
Instaluje kompilator lokalnie, zapisuje startowy tsconfig.json i uruchamia sprawdzenie bez zapisywania plików.
allowJs pozwala starym plikom .js stać obok nowych plików .ts podczas migracji; noEmit zostawia generowanie wyniku bundlerowi.
Sprawdzanie danych, których kompilator nie widzi
Strażnik w runtime, który zawęża typ
Funkcja naprawdę sprawdza wartość, a typ zwracany mówi kompilatorowi, co udowodniła.
Adnotacje
Typy parametru i wartości zwracanej są sprawdzane, a potem usuwane. Ciało funkcji pozostaje nietknięte.
Interfejs
Interfejs nie generuje żadnego wyniku. Istnieje wyłącznie dla checkera.
Enum
Zwykły enum staje się prawdziwym obiektem z odwrotnym mapowaniem, więc to wygenerowany kod, a nie usunięta składnia.
const enum
tsc wstawia składowe const enum bezpośrednio jako liczby i zostawia komentarz z oryginalną nazwą.
Błąd typu
tsc zgłasza: Argument of type 'string' is not assignable to parameter of type 'number'. Mimo to zapisuje plik, chyba że ustawiono noEmitOnError.