programowanieProgramista Fullstack

Opisz mechanikę operatorów Spread i Rest w TypeScript, jak działają one w kontekście ścisłej typizacji oraz na co zwrócić uwagę przy pracy z obiektami i tablicami?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

Historia pytania:

Spread (...) i Rest (...) to jedne z najpopularniejszych nowoczesnych konstrukcji składni, które pojawiły się w ES6. W TypeScript zyskały ścisłą typizację, dlatego użycie Spread i Rest stało się nie tylko wygodne, ale także bezpieczne, pod warunkiem przestrzegania ograniczeń typowych.

Problem:

Operacje Spread i Rest stają się źródłem błędów, jeśli nie uwzględniono typu wartości lub mieszane są niekompatybilne typy (na przykład, gdy łączone są obiekty z niekompatybilnymi właściwościami lub tablice różnych typów).

Rozwiązanie:

W TypeScript Spread służy do kopiowania lub łączenia właściwości obiektów i elementów tablic. Rest pozwala na zbieranie "pozostałych" elementów w funkcji lub tablicy, a ścisła typizacja sprawdza niekompatybilne przypadki, zapobiegając błędom na etapie kompilacji.

Przykład kodu:

// Spread z obiektami const base = { a: 1, b: 2 }; const extended = { ...base, c: 3 }; // extended: { a: number; b: number; c: number } // Rest w parametrach funkcji function sum(...args: number[]): number { return args.reduce((acc, val) => acc + val, 0); } // Spread w tablicach const arr = [1, 2, 3]; const newArr = [...arr, 4, 5];

Kluczowe cechy:

  • Spread zapewnia kopiowanie właściwości/elementów z kontrolą kompatybilności typów
  • Rest gwarantuje ścisły typ pozostałych parametrów
  • Błędy typów przy niepoprawnym łączeniu są wychwytywane już na etapie kompilacji

Pytania z pułapkami.

Czym różni się kopiowanie obiektu przez Spread od przypisania przez referencję?

Spread tworzy nowy obiekt z kopią wszystkich wyliczalnych właściwości, ale jeśli w obiekcie są zagnieżdżone obiekty, są one kopiowane przez referencję (shallow copy).

const base = { a: 1, nested: { x: 2 } }; const copy = { ...base }; copy.nested.x = 42; console.log(base.nested.x); // 42

Czy można za pomocą Spread kopiować tylko określone właściwości?

Nie, Spread kopiuje wszystkie wyliczalne właściwości obiektu. Do wybrania poszczególnych używa się destrukturyzacji:

const { a, ...rest } = { a: 1, b: 2, c: 3 }; // rest: { b: 2, c: 3 }

Co się stanie, jeśli połączymy przez Spread dwa obiekty z tymi samymi właściwościami? Jak to wpływa na typizację?

Właściwości z ostatniego obiektu nadpiszą właściwości poprzednich. Przy tym typ ostatniej właściwości będzie uznawany za ostateczny:

const a = { val: 1 }; const b = { val: 'hello' }; const merged = { ...a, ...b }; // merged: { val: string } (a nie number)

Błędy typowe i antywzorce

  • Używanie Spread do głębokiego klonowania zagnieżdżonych obiektów, chociaż to tylko "shallow copy"
  • Niepoprawna typizacja parametrów rest (określenie typu any[] zamiast konkretnego)
  • Łączenie obiektów z nakładającymi się niekompatybilnymi typami właściwości

Przykład z życia

Negatywny przypadek

W projekcie postanowiono połączyć parametry konfiguracyjne przez Spread. Jeden z obiektów miał właściwość timeout: number, a drugi — timeout: string. Żadne błędy nie zostały zauważone aż do runtime'u, kiedy funkcja nie działała z powodu niepoprawnego typu.

Zalety:

  • Szybka realizacja w kilku linijkach

Wady:

  • Błędy typizacji są niezauważalne, jeśli typ jest określony jako cualquier: any
  • Pułapki przy nadpisywaniu właściwości

Pozytywny przypadek

Użyto typizowanego Spread do łączenia ścisłych interfejsów, a także destrukturyzacji do oddzielenia zbędnych pól. Błędy wyłapał od razu kompilator.

Zalety:

  • Automatyczna kontrola i podświetlanie błędów przy niekompatybilności
  • Bezpieczne łączenie i modyfikacja typu

Wady:

  • Wymagana staranna konstrukcja interfejsów