Strona Główna /Najistotniejsze zmiany wprowadzone w nowej wersji TypeScript’a 5.5
09 sie 2024
5 min

Najistotniejsze zmiany wprowadzone w nowej wersji TypeScript’a 5.5

Tak jak i inne rzeczy (szczególnie w świecie technologii), TypeScript wciąż rozwija się poprzez zapewnienie najlepszych możliwych rozwiązań oraz czyniąc proces developmentu przyjemniejszym. Przejrzyjmy więc co zostało zmienione i jak możemy z tego skorzystać w codziennej pracy developera.

Wsparcie dla nowych metod

Wraz z wprowadzeniem najnowszej wersji TypeScript, nowe metody jak union() czy też dirrefence() są w pełni wspierane. Jeśli masz chęć przeczytać więcej informacji dotyczących tych metod kliknij tutaj tutaj. Celem zachowania zwartości artykułu, nie będziemy omawiać teraz każdej z tych metod pojedynczo, jakkolwiek możemy wspomnieć o kilku z nich. Rozważmy następujący przykład. 

const garage = new Set(["Volkswagen", "Moto bike"]);
const orders = new Set(["Lawn Mower", "Bike"]);


const sumUp = garage.union(orders);// {'Volkswagen','Moto bike', 'Lawn Mower', 'Bike'}

Jak możemy zauważyć mamy dwa różne Set’y (garage and orders). Do zmiennej sumUp przepisaliśmy rezultat wykonywania metody union na instacji Set’u ‘garage’. Rezultat wykonywania tej metody jest właściwy, ale jeśli wykorzystujemy wersję TypeScript niższą niż 5.5, zobaczymy następujący problem.

Property 'union' does not exist on type 'Set<string>'.(2339)

Celem uniknięcia tego blędu możemy oczywiście potraktować Set garage jako typ any.

const garage = new Set(["Volkswagen", "Moto bike"]) as any;

Ale jak wiemy, powinniśmy unikać używania typu any jeśli jest to tylko możliwe. Zamiast używania typu any, powinniśmy rozważyć podniesienie TypeScript do najnowszej wersji. Ten sam błąd możemy napotkać jeśli użyjemy np. metody difference.

Ulepszone Type Predicates

To uprawnienie może definitywnie zmienić sposób w jaki piszemy kod, szczególnie w przypadku kiedy pracujemy przy tablicach. Rozważmy następujący przypadek.

const grades = [3, 4, "A", "C", 2, 5];

Jak widzimy, zaprezentowana jest tablica składająca się z ocen, które mogą być zarówno w typie string jak i numer. Załóżmy, że chcemy poniższą tablicę przefiltrować przez typ oceny.

const numbericGrades = grades.filter((grade) => {
   return typeof grade === 'number'
}) // [3, 4, 2, 5] 

Dotychczas wszystko wygląda świetnie, ale jeśli spróbowalibyśmy przeiterować przez tablicę numericGrade celem uzyskania oceny średniej, ujrzelibyśmy TypeScriptowy błąd.

let averageGrade = 0
for(let i = 0; i++; i < numbericGrades.length) {
   const singleGrade = numbericGrades[i];
    averageGrade = averageGrade + singleGrade / numbericGrades.length;
}

Błąd wyświetlony

The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.(2362)
const singleGrade: string | number

Możemy uniknąć wskazanego błędu na kilka sposobów. Standardowo możemy wskazać,  wartość zmiennej singleGrade jako typ number

const singleGrade = numbericGrades[i] as number;

Oczywiście, możemy też użyć konstruktora obiektu Number celem wymuszenia wskazania, że wartość zmiennej singleGrade jest typu number. Nie jest to najlepsza praktyka, powinniśmy unikać tego typu rozwiązań jeśli jest to możliwe.

const singleGrade = Number(numbericGrades[i]);

Najnowsza wersja Typescript nie potrzebuje już tego rodzaju obejść. Możesz pisać swój kod tak jak wskazano w naszym for loop – TypeScript radzi sobie z tym rodzajem sytuacji 

Wpływ na inne biblioteki

Rozszerzając poniekąd poprzednią sekcję artykułu, możemy wspomnieć, że z najnowszych usprawnień TypeScript możemy skorzystać nie tylko w czystych plikach TypeScript lecz także w plikach które korzystają z zewnętrznych bibliotek, na przykład biblioteki RxJS. Nie jest celem tegoż artykułu omawiania całej biblioteki rxjs, jednakże celem pokazania jak możemy skorzystać z najnowszej wersji TypeScript, zerknijmy na następujący przykład.

class Example {
  private _myArr = of("11", 1);
}

Jak widzimy na załączonym przykładzie, utworzyliśmy observable poprzez użycie operatora  of właściwego dla biblioteki RxJS. Podobnie jak w poprzednim przykładzie chcemy przefiltrować wartość observable mając na uwadze typ wartości.

this._myArr.
  pipe(
    filter((el) => {
      return typeof el !== 'string'
    }),
    tap((filteredElement) => 
      console.log(filteredElement * 10)
    )
  ).subscribe()

Jeśli korzystalibyśmy ze starszych wersji TypeScript, ujrzelibyśmy następujący błąd.

The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.(2362)

Sprawdzanie Syntaxu Wyrażeń Regexowych.

Wraz z wprowadzeniem najnowszej wersji TypeScript, wyrażenia regexowe i ich syntax nie są już pomijane. Od teraz możemy korzystać z możliwości sprawdzania syntaxu przez TypeScript. Jest to z pewnością duża zmiana, ale nadal musimy wykazać się czujnością. Sprawdzenie syntaxu jest przeprowadzane jedynie dla regularnych expression literals. Jeśli będziemy chcieli skorzystać z kontruktura obiektu RegExp, to sprawdzanie syntaxu nie zadziała.

const regPattern = /angular18(/ //error:  ')' expected.
const regExp =  RegExp(" /angular18(/") //no error thrown


//Typescript Version Lower than 5.5:
const regPattern = /angular18(/ /no error thrown

Ulepszone zawężenie typów 

Kolejnym kamieniem milowym w procesie jest ułatwienie dostępu to properties obiektu poprzez usprawnienie zawężania typów. Zerknijmy na następujący przykład:

type ObjectType = Record<number | string, number | string>;


const someObject: ObjectType = {
   10: 30
}


function multiplyVal(obj: ObjectType, key: number | string) {
   if (typeof obj[key] === "number") {
       return {
           key: obj[key] * 10
       }
   } else {
       return {
           key: 'Key is not a number'
       }
   }
}

Utworzyliśmy funkcję, która sprawdza czy wartość property obiektu jest typu number, a jeśli tak, to zwracana jest przemnożona wartość klucza. W każdym innym wypadku, obiekt zwróci property o wartości zahardcodowanego tekstu. Do tej pory, deweloperzy w przypadku napisania powyższego kodu, zwróciliby uwagę na następujący błąd:

The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.(2362)

Ten błąd nie występuje w najnowszej wersji TypeScipt. Co więcej nie musimy już obchodzić problemu w następujący sposób.

const value = Number(obj[key])
    return {
        key: value * 10
    }

Ulepszony Type Imports in JSDoc

Ostatnia wersja TypeScript wspiera nowym @Import tag. Celem wprowadzenia tego ulepszenia było ograniczenie problemów z importowanymi typami w dokumentacji, jako, że te istnieją jedynie podczas runtime naszej aplikacji. Spójrzmy: 

/** @import { ObjType } from "types" */


/**
* @param { ObjType } objExample
*/


function myFunc(objExample) {
   // ...
}

Przed ostatnimi zmianami, deweloperzy musieli rozważyć napisanie obejść takich jak te:

/**
* @param {import("Types").ObjType} objExample
*/

Obecnie, dzięki zmianom w najnowszej wersji TypeScript nie musimy już tego robic

Waga naszej paczki

Wspomnieć należy, że najnowsza wersja TypeScript została nieco ‘odchudzona’ w stosunku do poprzedniej . Udało się to osiągnąć poprzez przebudowanie plików tsserver.js i typingInstaller.js. Obecnie są one częścią publicznego API i nie produkują własnych bundlów

Before After Difference(%)
Packed 5.51 MiB 3.76 MiB 31.66%
Unpacked 30.18 MiB 20.36 MiB 32.55%

Angular a Typescript

Jeśli korzystasz z framawork’a Angular i chcesz skorzystać z najnowszych usprawnień TypeScript, musisz podnieść wersję Angulara do wersji 18.1. Od tej wersji Angulara możesz swobodnie korzystać z TypeScript 5.5. Możesz przeczytać więcej temat nowej wersji Angulara tutaj.

Podsumowanie

Jak wskazano w artykule, najnowsza wersja TypeScript wprowadziła wiele zmian. Z każdą kolejną iteracją TypeScript staje się coraz to lepszym narzędziem przydatnym w codziennej pracy developerów. Mamy nadzieję, że następna wersja TypeScript wprowadzi równie owocne zmiany co ostatnia wersja.

Dziękuję za przeczytanie mojego artykułu

Podziel się artykułem

Zapisz się na nasz newsletter

Dołącz do community Angular.love i bądź na bieżąco z trendami.