programowanieFullstack developer

Jak działa mechanizm dynamicznego dostępu do właściwości (Index Signature) w TypeScript? Do czego się go używa i jakie są główne pułapki?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

Index Signature to mechanizm opisu typu obiektów, których klucze są z góry nieznane (lub mogą być dodawane dynamicznie), a wartości odpowiadają określonemu typowi. Umożliwia tworzenie obiektów-słowników (map/dictionary), gdzie lista właściwości jest nieznana na etapie kompilacji.

Historia pytania: w JavaScript obiekty często występują jako tablice asocjacyjne. Statyczna typizacja TypeScript wymaga wskazania typów kluczy i wartości. Index Signature rozwiązuje główny problem: opisanie obiektu, gdzie klucz — nie jest sztywno zapisanym właściwością, a stringiem (lub liczbą), a wartości — określonego typu.

Problem: podczas pracy z takimi obiektami można napotkać sytuację, w których znane właściwości obiektu kolidują z index signature, lub tracona jest informacja o konkretnej właściwości. Są pewne niuanse związane z dziedziczonymi typami i rozszerzeniem struktury słownika.

Rozwiązanie: Index Signature jest używany do opisu dynamicznych właściwości, zazwyczaj z kluczem typu string lub number, na przykład dla kolekcji, obiektów cache lub odpowiedzi API w formacie { [key: string]: T }. Aby zachować kontrolę nad typem, konieczne jest opisanie i stałych właściwości oraz index signature razem, lub, jeśli to konieczne — stworzenie typów union.

Przykład kodu:

interface StringNumberMap { [key: string]: number; } const map: StringNumberMap = { apples: 2, oranges: 5, bananas: 3 };

Kluczowe cechy:

  • Umożliwia opisywanie obiektów z dynamicznym zestawem właściwości
  • Klucz może być stringiem, liczbą, symbolem
  • Index signature wpływa na typizację wszystkich właściwości obiektu

Pytania z podstępem.

Co się stanie, jeśli dodasz stałą właściwość z niekompatybilnym typem do interfejsu z index signature?

TypeScript zgłosi błąd, jeśli typ właściwości nie jest zgodny z typem określonym w index signature.

interface BadDict { [key: string]: number; error: string; // Błąd: string niezgodny z number }

Czy można zadeklarować kilka index signature z różnymi typami kluczy (number i string) jednocześnie?

Tak, jest to możliwe, ale istnieje pewien niuans: w TypeScript klucze typu number automatycznie konwertowane są na stringi. Index signature z number to tylko synonim dla kluczy string.

interface NumStrDict { [key: string]: number; [key: number]: number; }

Czy można używać typów union lub interfejsów dla wartości w index signature?

Tak, wartość może być typem union lub interfejsem. W ten sposób można opisać słowniki złożonych obiektów.

interface Dict { [key: string]: string | number; }

Typowe błędy i antywzorce

  • Niezgodność typu stałych właściwości i index signature
  • Używanie dowolnego typu wartości (np. [key: string]: any)
  • Luki w dokumentacji, niejasność dotycząca tego, co może być kluczem

Przykład z życia

Negatywny przypadek

W interfejsie odpowiedzi API użyto [key: string]: any. Później zwracany obiekt zawierał dane różnych struktur, co doprowadziło do błędów w czasie wykonywania i utrudniło utrzymanie kodu.

Zalety:

  • Szybkie opisanie dowolnej struktury
  • Prostota w zastosowaniu

Wady:

  • Łatwo popełnić błąd typizacji
  • Niejasna struktura obiektów

Pozytywny przypadek

Opisano interfejs obiektu cache, gdzie wartości są ściśle określonego typu (np. UserData), z komentarzem, że klucz — userId (string):

interface UserCache { [userId: string]: UserData; }

Zalety:

  • Jasna typizacja
  • Łatwe w użyciu i rozszerzaniu

Wady:

  • Nie chroni przed nieprawidłowym użyciem kluczy
  • Może być trudno łączyć z właściwościami stałymi