TypeScript jest wolniejszy od JS, przy prostych iteracjach różnica jest kilkuprocentowa, ale przy złożonych operacjach różnica jest ogromna. Wynika to z budowy TS, który jest transpilowany do JS (plus dodatkowy narzut).
Osobiście uważam, że najważniejsza jest wydajność kodu i to ją się powinno optymalizować, a na drugim miejscu stawiam wygodę i szybkość pisania kodu. Szczególnie jest to ważne w projektach długofalowych, które mają z założenia pracować kilka lat. Czemu to jest takie ważne? Bo jak zabraknie nam mocy obliczeniowej w skalowaniu pionowym (coraz mocniejsza maszyna), musimy się przenieść na skalowanie poziome (cloud hosting, clustering, itd.). Koszt przepisania aplikacji 1-instance do klastrowej przekracza często 100% wartości projektu. dodatkowo koszt dostawienia nowej maszyny nie jest współmierny do wzrostu przychodu i firma decyduje się na straty związane ze skalowaniem albo ograniczenie dostępu do usługi i brak rozwoju, a podstawową zasadą każdej firmy jest rozwój (jeśli firma się nie rozwija, to umrze w przeciągu 5 lat). Dlatego lepiej wybrać szybki język i pisać kod 2 razy dłużej (koszt jednorazowy) niż płacić 3x więcej za hosting każdego miesiąca.
Dochodzi kolejna kwestia
Bezpieczeństwo typowania. O tym już wspomniałem kilka razy, że typowanie działa wyłącznie w obrębie naszego kodu. Problemem są dane wchodzące do apki z zewnątrz - czy to 3rd party API czy dane od użytkownika. To, że typujemy sobie jakąś zmienną na string to nie znaczy, że apka sama nam sprawdzi typ zmiennej po transpilowaniu. Jeśli nie dopiszemy kodu do sprawdzenia typu zmiennej ręcznie to wywalimy apkę, tak samo w JS. Dwa przykłady z życia wzięte - Zewnętrzne API zmienia swoją strukturę z dnia na dzień bez wystawiania wyższej wersji (podmieniają istniejące endpointy, niestety czasami się to zdarza). Jeśli nie napiszemy w kodzie TS/JS sprawdzania jaki typ nam wpada to uwalimy apkę. Drugi przykład to komunikacja Frontend/Backend. Robimy sobie wspólne interefejsy na wymianę danych (np. logowanie email/hasło - 2 stringi), w TS wszystko nam się pięknie kompiluje na froncie i backu, ale nie napisaliśmy linijki do sprawdzenia typu i zamiast stringów wysyłamy obiekty. Wywalamy apkę na backu.
Retranspilacja kodu
Każda zmiana w kodzie to kompilowanie całej aplikacji, zajmuje to kilka sekund, ale jeśli w ciągu 8 godzin pracy musimy kompilować kod 300 razy to mamy stracone 15-30 minut na czekaniu. A co jak mamy poważny błąd w kodzie i trzeba szybko naprawić produkcję? W JS można zrobić poprawkę w Git, wrzucić na serwer i zrobić restart 1 usługi, a jak coś jest mega pilne to możemy zmianę wprowadzić od razu na serwerze i zrobić szybki restart - w idealnym świecie nie ma miejsca na takie akcje, ale praktyka wygląda inaczej. Osobiście kilkanaście razy naprawiałem tak błędy w wersji produkcyjnej. W TS nie możemy bezpośrednio edytować kodu, musimy edytować źródła i odpalać kompilator, co zajmuje dużo czasu. Jeśli nie do końca wiemy czy zmiana pomoże to tracimy kupę czasu, a produkcja wisi.
Typowanie jest super
ale tylko jeśli jest natywnie wbudowane w język (Java, Rust). Jeśli dochodzi do transpilacji kodu to jesteśmy w dupie. Dodatkowo uważam, że najlepsze są języki elastyczne - typujesz jeśli chcesz, a nie musisz. Świetnie zapowiada się Deno, nowe dziecko twórcy Node. W Deno jest natywnie wbudowany kompilator TypeScript. Kodujemy w TS i wirtualna maszyna transpiluje kod do Rusta. Nie ma problemu z wydajnością jak w przypadku TS do JS do V8. niestety Deno to raczkujący projekt i nie mamy pewności, że pewnego dnia ujrzymy stabilną wersję.
A tak na koniec pół żartem, pół serio - jeśli potrzebujesz typowania, bo gubisz się w kodzie to jesteś gamoń, nie programista 😛