Menu

Tablice w TypeScript: typy, tablice obiektów, map i filter

Jak typować tablice w TypeScript: T[] a Array<T>, tablice obiektów, tablice z kilkoma typami, tablice tylko do odczytu i co zwracają map, filter, reduce i find. Do tego pułapka z includes w tablicach literałów.

Na tej stronie są działające edytory: edytuj, uruchamiaj i od razu zobacz wynik.

Typ tablicy w TypeScript to typ elementu, a po nim []: string[] to tablica napisów, number[] tablica liczb. Zapis generyczny Array<string> to ten sam typ. Gdy tablica ma typ, każdy dodawany i każdy odczytywany element ma ten typ.

Linia z @ts-expect-error to błąd kompilacji (TS2345). Tutaj jest oznaczona jako oczekiwana, żeby blok nadal się uruchamiał, a ponieważ typy znikają, 42 naprawdę trafia do tablicy w czasie działania: wynik to pokazuje.

string[] a Array<string>

ZapisTo samo coUwagi
string[]Array<string>Najczęstszy zapis.
(string | number)[]Array<string | number>Nawiasy są wymagane: string | number[] oznacza „napis albo tablica liczb”.
readonly string[]ReadonlyArray<string>Bez push, pop, sort i przypisania przez indeks.
User[]Array<User>Tablice obiektów używają typu obiektu.
string[][]Array<Array<string>>Tablica dwuwymiarowa (siatka).

Wybierz jeden styl dla całego projektu. Reguła array-type z typescript-eslint domyślnie wybiera T[].

Tablice obiektów

Opisz element aliasem typu albo interfejsem, a potem użyj Type[]. Wszystko, co odczytasz z tablicy, jest sprawdzane względem tego kształtu.

Literał obiektowy dodany do users musi dokładnie pasować do User: brak admin albo literówka w nazwie właściwości to błąd kompilacji.

Otypowane map, filter, reduce i find

Metody tablic są generyczne, więc ich wyniki mają typy. To, co każda metoda robi w czasie działania, opisuje strona o metodach tablic w JavaScript; TypeScript dodaje typy:

MetodaTyp wyniku dla T[]
map(fn)U[], gdzie U to typ zwracany przez fn
filter(fn)T[] (albo węższy typ, zobacz niżej)
find(fn)T | undefined
findIndex(fn), indexOf(x)number (-1, gdy brak)
some(fn), every(fn), includes(x)boolean
reduce(fn, init)typ init (albo argument typu, reduce<R>(...))
at(i)T | undefined
join(sep)string

Ostatni przykład działa, bo TypeScript (od wersji 5.5) wnioskuje, że (n) => n !== undefined jest predykatem typu, więc filter zwraca number[] zamiast (number | undefined)[]. Dla sprawdzeń, których nie potrafi wywnioskować, napisz predykat sam: filter((x): x is User => x !== null).

Tablice z więcej niż jednym typem

Unia jako typ elementu pozwala na mieszankę. Unia typów tablic już nie:

Gdy pozycje mają stałe typy, jak para [name, age], użyj krotki: [string, number] wie, że indeks 0 to napis, a indeks 1 to liczba, czego (string | number)[] nie wie.

Tablice tylko do odczytu

readonly T[] usuwa wszystkie metody, które zmieniają tablicę. Używaj tego dla parametrów, których funkcja nie powinna zmieniać, oraz dla stałych.

index.ts(3,12): error TS2339: Property 'push' does not exist on type 'readonly number[]'.

Usuń linię z push, a blok wypisze 4. Zmienną tablicę number[] zawsze można przekazać tam, gdzie oczekiwane jest readonly number[], więc parametry tylko do odczytu nic nie kosztują wywołujących. Sprawdzenie działa tylko w czasie kompilacji: w czasie działania to zwykła tablica. Żeby posortować tablicę tylko do odczytu, posortuj kopię: [...values].sort().

Pułapka z includes w tablicach literałów

as const zamienia tablicę w krotkę tylko do odczytu złożoną z typów literałowych. To przydatne dla listy dozwolonych wartości, ale jej includes przyjmuje wtedy tylko te literały:

Opakowanie sprawdzenia w strażnika typu (value is Color) sprawia, że poszerzenie odbywa się raz, a wywołujący dostają z powrotem zawężoną wartość.

Indeksowanie i puste tablice

Odczyt arr[i] daje typ T, nawet gdy i jest poza zakresem, a wartość w czasie działania to undefined. at(i) ma typ T | undefined, a opcja kompilatora noUncheckedIndexedAccess sprawia, że zwykłe indeksowanie też zwraca T | undefined.

queue[0].toUpperCase() skompilowałoby się, a potem rzuciło TypeError w czasie działania. Gdy indeksu może brakować, wybierz at(), sprawdzenie długości albo noUncheckedIndexedAccess.

Najczęściej zadawane pytania

Jak zadeklarować typ tablicy w TypeScript?

Napisz typ elementu, a po nim []: let names: string[] = ["a", "b"]. Forma generyczna Array<string> znaczy dokładnie to samo. Dla tablicy obiektów użyj typu obiektowego albo interfejsu jako typu elementu: User[].

Czym różni się string[] od Array<string>?

Niczym: to dwa zapisy tego samego typu. string[] jest częstszy. Forma generyczna czyta się lepiej przy złożonych typach elementów, a dla tablic tylko do odczytu readonly string[] i ReadonlyArray<string> również znaczą to samo.

Dlaczego find zwraca undefined w TypeScript?

array.find() zwraca T | undefined, bo może nic nie pasować. Przy strict musisz obsłużyć przypadek undefined, sprawdzeniem if, opcjonalnym łańcuchowaniem (found?.name) albo wartością domyślną (found ?? fallback), zanim użyjesz wyniku.

Jak otypować tablicę z wieloma typami w TypeScript?

Użyj unii jako typu elementu w nawiasach: (string | number)[] to tablica, w której każdy element jest napisem albo liczbą. To coś innego niż string[] | number[], czyli albo tablica samych napisów, albo tablica samych liczb. Dla stałej kolejności typów, na przykład [string, number], użyj krotki.

Dlaczego includes zgłasza błąd na tablicy as const?

Tablica literałów tylko do odczytu, taka jak ["red", "green"] as const, ma includes(searchElement: "red" | "green"), więc przekazanie zwykłego string to błąd TS2345. Na czas sprawdzenia poszerz typ tablicy, (COLORS as readonly string[]).includes(input), najlepiej wewnątrz strażnika typu, który zawęzi input do unii literałów.

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ