programowanieFullstack developer

Jak działa typizacja tablic w TypeScript, jak poprawnie deklarować tablice z elementami różnych typów i jakie są sposoby ich opisywania za pomocą krotek (tuples)? Podaj przykłady i wyjaśnij możliwe błędy związane z użytkowaniem takich struktur.

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

W TypeScript tablice opisuje się na dwa główne sposoby: typ[] oraz Array<typ>. Dla tablic z elementami różnych typów używa się typów unijnych (union types) lub krotek (tuples), które pozwalają opisywać ustalony zestaw elementów różnych typów i ilości.

Deklaracje tablic:

let numbers: number[] = [1, 2, 3]; let strings: Array<string> = ['a', 'b', 'c'];

Tablica z elementami różnych typów:

let mixed: (string | number)[] = [1, 'a', 2];

Krotki (tuples):

let tuple: [string, number, boolean] = ['hello', 42, true];

Z krotkami łatwiej pracować, gdy oczekuje się ustalonej struktury (na przykład, aby zwrócić z funkcji kilka różnych wartości typu jednocześnie), natomiast z tablicami — gdy liczba i typ elementów mogą być pomieszane lub nieznane z góry.

Pytanie z haczykiem.

Czy po zdefiniowaniu krotki o długości N można dodać do niej elementy za pomocą push? Jak to wpływa na typizację?

Odpowiedź: Tak, można dodawać do krotki elementy — kompilator na to zezwala, chociaż narusza to założenie ograniczenia długości krotki. Typy nowych elementów będą rzutowane na union wszystkich możliwych typów elementów krotki:

let tuple: [number, string] = [42, 'foo']; tuple.push(true); // OK! tuple teraz: [number, string, boolean], ale typ się nie zaktualizował, a błędu nie ma! console.log(tuple); // [42, 'foo', true]

Dlatego pracując z krotkami i ich zmiennością, należy to kontrolować ręcznie lub uczynić je readonly.

Przykłady rzeczywistych błędów z powodu braku znajomości subtelności tematu.


Historia

Programista opisał funkcję, która zwraca krotkę [number, string], ale potem zaczął dodawać do wyniku elementy przez push. Doprowadziło to do rozbieżności typów: późniejszy kod oczekiwał dokładnie dwóch elementów o określonych typach, ale otrzymywał tablicę o zmiennej długości, co prowadziło do błędów w czasie wykonywania podczas rozpakowywania wartości i odczytu z nieistniejących indeksów.


Historia

Do przechowywania tablicy wartości różnych typów użyto tablicy any[], uważając to za uniwersalne rozwiązanie. W rezultacie TypeScript przestał sprawdzać poprawność typów, a logika aplikacji zaczęła "łamana" przez niepoprawne przekształcenia typów, które nie powodowały błędów kompilacji.


Historia

W projekcie tablica była opisywana albo przez typ[], albo przez Array<typ> — ale w niektórych miejscach dopuszczano zapis let arr: any[] (aby pracować "z czymkolwiek"). Z tego powodu pojawiały się niekontrolowane przekształcenia, funkcja przyjmowała każdą tablicę, co prowadziło do błędów w czasie wykonywania podczas próby wywołania niepoprawnych metod dla elementów różnych typów.