Do opisywania złożonych struktur danych w TypeScript używa się interfejsów (interface) oraz aliasów typów (type). Można je łączyć z obiektami, tablicami i zagnieżdżonymi typami w celu ścisłej typizacji złożonych kolekcji.
Dla zagnieżdżonego obiektu:
interface Address { city: string; zip: number; } interface UserProfile { name: string; age: number; address: Address; }
Dla tablicy z różnymi typami:
// Krotka let tuple: [string, number] = ['John', 30]; // Tablice z typami unii let arr: (string | number)[] = [1, 'a', 2, 'b']; // Tablica obiektów let users: UserProfile[] = [ {...}, {...} ];
Gdy struktury są skomplikowane i zawierają opcjonalne pola, używa się ?, łączy z typami Partial, Record, Mapped Types lub typami rekurencyjnymi dla zagnieżdżonych drzew.
Pytanie: Czy można użyć interfejsu do opisu tablicy z różnymi typami elementów (np. [string, number, boolean])?
Odpowiedź: Nie. W takim przypadku lepiej użyć krotek — interfejsy nie nadają się do ustalonych pozycji i typów. Krotki pozwalają dokładnie określić typy na każdej pozycji.
type MyTuple = [string, number, boolean]; let foo: MyTuple = ['ok', 12, false];
Historia
W projekcie błędnie opisano złożoną strukturę: dla tablicy mieszanych typów użyto any[] zamiast poprawnej krotki lub typu unii. W rezultacie, w jednym z elementów znalazła się wartość innego typu, co doprowadziło do błędu w logice biznesowej (operacja arytmetyczna ze stringiem).
Historia
W strukturze danych głęboko zagnieżdżone obiekty były zadeklarowane bez użycia typów rekurencyjnych lub Partial. Próba dodania nowego poddrzewa do węzła drzewa wywoływała błąd kompilatora, a programiści omijali to przez downcast do any, co później spowodowało błędy podczas działania w produkcji.
Historia
Obiekt z opisem profilu użytkownika był częściowo opcjonalny, ale programista nie użył ?. Przy odbieraniu danych z serwera TypeScript nie zgłaszał błędów, a aplikacja padała, próbując uzyskać dostęp do pól, które nie istniały w obiekcie.