programowanieProgramista frontendowy

Czym są typy rozproszone (Distributive Types) w TypeScript, gdzie są stosowane i jakie cechy należy uwzględnić podczas pracy z nimi?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź

Typy rozproszone (Distributive Types) to cecha TypeScript, która manifestuje się podczas pracy z typami warunkowymi (T extends U ? X : Y). Gdy zmienna-typ po lewej stronie extends jest unią (union), TypeScript rozdziela warunek na każdy element unii.

Przykład:

// "Test<A> | Test<B> | Test<C>" type Test<T> = T extends string ? () => string : () => number; type Result = Test<'A' | 'B' | 'C'>;

Tutaj Result rozdzieli się jak:

  • Test<'A'> | Test<'B'> | Test<'C'>

Kiedy stosować — do pisania uniwersalnych interfejsów API, manipulacji nad unią, np. do filtrowania lub dopasowywania do wzorca.

Cechy:

  • Jeśli opakujesz T w krotkę [T], rozdzielenie się nie nastąpi. To sposób na "wyłączenie" rozproszenia.
  • Rozdzielenie działa tylko dla zmiennych typowych (a nie literali).

Pytanie z podstępem

Pytanie: Czy typ T[] extends number[] ? true : false będzie rozproszony?

Prawidłowa odpowiedź: Nie, rozproszenie występuje tylko wtedy, gdy po lewej stronie jest zmienna-typ bez opakowania w tablicę lub krotkę. Na przykład, typ warunkowy T extends number ? ... będzie rozdzielać, ale T[] extends number[] ? ... — nie.


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


Historia

Projekt: Biblioteka walidacji props dla komponentów React. Chcieliśmy zaimplementować typ, który przekształca unijne propsy w surowy interfejs, ale z powodu braku wiedzy o rozproszeniu typ stał się niespodziewanie skomplikowany (zmieszały się właściwości członków unii). Naprawiliśmy to, dodając opakowanie [T], aby rozproszenie się nie odbywało.


Historia

Projekt: Tworzyliśmy jedną funkcję-obserwatora dla wszystkich typów zdarzeń. W typie warunkowym oczekiwano, że funkcja przyjmie każdy typ zdarzenia przez rozproszenie, ale bez jego wyraźnego użycia, niepoprawnie zaimplementowaliśmy obsługę, co doprowadziło do błędnych typów argumentów (unia zamiast oddzielnego wywołania dla każdego typu).


Historia

Projekt: Podczas tworzenia własnych typów narzędziowych (typu Exclude, Extract) zapomnieliśmy, że rozproszenie nie nastąpi dla krotek i tablic. W rezultacie typ Exclude nie działał dla tablic (na przykład typ Exclude<["a"|"b"], "b"> nie usuwał "b").