Typescript 5.3 nie jest rewolucją, ale jest ewolucją w dobrą stronę.Nowa wersja Typescripta wprowadza wiele zmian. Z perspektywy dewelopera są to zmiany w najważniejszych obszarach. Typescript 5.3 wprowadza zmiany w obszarach typowania, wydajności oraz kilku mniejszych obszarach. Te zmiany mają bardzo duży wpływ na zadowolenie programisty z korzystania z języka Typescript.
Zawężanie typów w switch(true)
W instrukcji switch możemy zawierać nie tylko wartości ale również wyrażenia logiczne.To rozwiązanie można zastosować aby zapewnić lepszą jakość i czytelność kodu. Najczęstszym powodem użycia tego rozwiązania jest chęć zastąpienia skomplikowanych instrukcji warunkowych if/else.W Typescript 5.3 otrzymujemy lepsze zawężanie typów, dzięki któremu mamy większą pewność, że kod który zostanie wykonany w danym casie będzie operował na typie, który jest tam spodziewany. Co spowoduje brak pojawiania się nielogicznych błędów na etapie kompilacji. Poniżej przykład obrazujący benefity płynące z wprowadzenie tej nowej funkcjonalności w Typescript 5.3:
1 2 3 4 5 6 7 8 9 10 |
function f(x: unknown) { switch (true) { case typeof value === 'string': console.log("value is a 'string' here"); case Array.isArray(x): console.log("value is a 'string | any[]' here"); default: console.log("value is a 'unknown' here"); } } |
Zawężanie typów w bezpośrednim porównywaniu True/False
Czasami ze względu na jakość kodu oraz jego czytelność może zaistnieć potrzeba użycia porównania zmiennej bezpośrednio do wartości True/False w instrukcji warunkowej. W Typescript 5.3 otrzymujemy lepsze zawężanie typów, które możemy użyć w przypadku użycia takiego bezpośredniego porównania w instrukcji warunkowej if/else.W kodzie z przykładu poniżej przed zmianą otrzymałbyś błąd o tym, że atrybut propOnlyInFirstInterface
nie istnieje, ale w wersji Typescript 5.3 tego błędu już nie otrzymasz ponieważ Typescript wydedukuje, że x
jest instancją interfejsu FirstInterface
co oznacza, że atrybut propOnlyInFirstInterface
jest zdefiniowany.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
interface FirstInterface { propOnlyInFirstInterface: string; } interface SecondInterface { propOnlyInSecondInterface: string; } type FirstOrSecondInterfaceType = FirstInterface | SecondInterface; function isFirstInterfaceInstance( x: FirstOrSecondInterfaceType ): x is FirstInterface { return 'propOnlyInFirstInterface' in x; } function exampleFunction(x: FirstOrSecondInterfaceType) { if (isFirstInterfaceInstance(x) === true) { console.log(x.propOnlyInFirstInterface); // works, no errors during compilation } } |
Użycie Symbol.hasInstance w trakcie typowania
Typescript 5.3 wprowadza usprawnienie w postaci użycia instanceof
w trakcie typowania instancji klas zdefiniowanych przez programistę. Po tej zmianie kompilator zwraca typ bazując na zwracanej wartości przez metodę Symbol.hasInstance.
Sprawdzanie dostępności atrybutu przy użycia słowa kluczowego Super
Typescript 5.3 ściślej dokonuje sprawdzenia dostępności atrybutów klasy bazowej w przypadku użycia słowa kluczowego Super
.Po pierwsze, aby zrozumieć jakie korzyści płyną z wprowadzenia tego usprawnienia musimy wiedzieć, że z pomocą słowa kluczowego Super
możemy wywoływać tylko to co zostało zawarte w prototypie klasy. Jeżeli więc coś zadeklarujemy jako pole w klasie, a nie jako metodę to to pole nie pojawi się w prototypie klasy. I w takim przypadku wywołanie tego pola jako funkcji za pomocą słowa kluczowego Super
zaskutkuje pojawieniem się błędu w czasie wykonywania kodu. Prościej mówiąc, możemy z pomocą słowa kluczowego Super
wywołać tylko i wyłącznie coś co jest faktycznie metodą klasy. W TypeScript 5.3 taki błąd zostanie wyłapany na etapie kompilacji. Przyklad poniżej:
1 2 3 4 5 6 7 8 9 10 11 |
class BaseClass { field = () => { console.log('field executed!'); }; } class Example extends BaseClass { method() { super.field(); //throw type-checking error } } new Example().method(); |
Pominięcie parsowania JSDoc
W celu usprawnienia wydajności kompilacji Typescript uruchomiony z użyciem tsc w trakcie kompilacji nie będzie marnował czasu i zasobów na parsowanie JSDoc. Przez to otrzymasz wynik kompilacji znacznie wcześniej w trybie –watch
Ujednolicenie tsserverlibrary.js i typescript.js
W Typescript 5.3 zawartość tsserverlibrary.js jest zawarta w pliku typescript.js. Aktualnie plik tsserverlibrary.js jedynie eksportuje plik typescript.js. Wcześniej obydwa moduły zawierały wiele zduplikowanego kodu i bardzo łatwo było doprowadzić do sytuacji w której obydwa te pliki zostały zawarte w finalnej paczce. Jak można zobaczyć w tabeli znajdującej się poniżej, ta zmiana średnio zredukowała rozmiar paczki o około 20%.
Przed | Po | Różnica | |
Spakowana | 6.90 MiB | 5.48 MiB | -1.42 MiB( -20.61% ) |
Rozpakowana | 38.74 MiB | 30.41 MiB | -8.33 MiB( -21.50% ) |
Zastąpienie import asercji importem atrybutów
TypeScript 5.3 pozwala na zawarcie dodatkowej informacji w trakcie importowania na temat tego co zostaje importowane, informacja ta może zostać wykorzystana przez przeglądarkę lub runtime. Jeżeli importujesz plik JSON to możesz dołączyć informację o tym, że jest to JSON do importu. Może to zostać również użyte w przypadku dynamicznych importów. Od teraz wykorzystywany do tego celu jest import
a nie assert
. Dla przykładu tak to wygląda w przypadku statycznego importu:
1 |
import mockedData from "./mocked-data.json" with { type: "json" }; |
Przykład użycia w przypadku dynamicznego importu:
1 2 3 |
const mockedData = await import("./mocked-data.json", { with: { type: "json" } }); |
Wsparcie dla resolution-mode w importowaniu typów
Funkcjonalność resolution-mode
pozwoli ci na wyspecyfikowanie czy w trakcie importu ma zostać użyta stara składnia require
czy nowa import
. Po raz pierwszy ta funkcjonalność pojawiła się w Typescript 4.7, ale teraz została oznaczona jako stabilna funkcjonalność. TypeScript 5.3 dodatkowo wspiera tą funkcjonalność jako atrybut w trakcie importowania typu, dla przykładu:
1 2 3 4 5 6 7 8 |
// Resolve `pkg` as if we were importing with a `require()` import type { TypeFromRequire } from "pkg" with { "resolution-mode": "require" }; // Resolve `pkg` as if we were importing with an `import` import type { TypeFromImport } from "pkg" with { "resolution-mode": "import" }; |
Interaktywne wyszukiwanie typów w edytorze
W Typescript 5.3 możesz bardzo łatwo przechodzić do definicji typu z użyciem swojego edytora kodu.Przykładowo jeśli dokonujesz mapowania elementów w tablicy, to aktualnie masz możliwość najechania myszką na przewidziany przez Typescript typ iterowanego elementu i po kliknięciu zostaniesz przeniesiony do definicji wyżej wspomnianego typu. Ta funkcjonalność znacząco ułatwi życie osobom, które intensywnie refactorują swój kod oraz programistą pracującym w rozległych projektach zawierających bardzo dużą ilość typów.Jeśli chcesz wypróbować tą nową funkcjonalność to warto skorzystać z lekkiego IDE, dobrym przykładem takiego typu edytora będzie Visual studio code, bo w odróżnieniu od innych IDE nie posiada on dużej ilości własnych rozwiązań( przykładowo jak WebStorm). Dlatego właśnie każda nowa funkcjonalność tego typu w języku Typescript zwiększa komfort z korzystania z lekkich IDE takich jak VSC.
Podsumowanie
Zmiany wprowadzone w TypeScript 5.3 spowodują realną zmianę w zakresie usprawnienia zawężania typów oraz wydajności Typescriptu. Jest jasne ,że dla ludzi odpowiedzialnych za rozwój języka Typescript priorytetem jest zadowolenie deweloperów — i to jest godne pochwały!
Jakie kolejne zmiany czekają nas w TypeScript? Na ten moment nie mamy konkretnych informacji,ale na podstawie spekulacji można wnioskować, że wersja 5.4 prawdopodobnie wprowadzi takie zmiany jak redukcja intersections typów pomiędzy typami zmiennych a typami prostymi, oraz dokładniejsze ograniczanie warunkowe typów. To jednak są tylko spekulacje — na razie będziemy musieli poczekać i zobaczyć co przyniesie nam przyszłość!
Leave a Reply