programowanieProgramista Fullstack

Jak działa rozszerzanie typów (extends), jakie są niuanse użycia z typami i interfejsami, i jak wpływa to na strukturę twojego projektu?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź

W TypeScript można rozszerzać (dziedziczyć) typy zarówno za pomocą interface extends, jak i za pomocą type & type (typy przecięcia). Interfejsy mogą również rozszerzać typy, i odwrotnie.

Interfejsy używają słowa kluczowego extends do dziedziczenia właściwości:

interface Animal { name: string; } interface Bird extends Animal { wings: number; }

Typy mogą być łączone przez &:

type Animal = { name: string }; type Bird = Animal & { wings: number };

Ponadto interfejs może rozszerzać inny typ:

type Base = { id: number }; interface Derived extends Base { description: string; }

Cechy szczególne:

  • Interfejsy wspierają deklaracyjne łączenie (declaration merging), typy — nie.
  • Interfejsy są zalecane, gdy oczekuje się rozszerzenia innych bytów (na przykład dla bibliotek).
  • Zagnieżdżone extends mogą prowadzić do złożonej hierarchii, komplikować wsparcie i stwarzać konflikty nazw.

Pytanie przewrotne

Czy typ (type) może być rozszerzany przez interfejs lub odwrotnie? Jaki błąd popełnia większość?

Wielu uważa, że można rozszerzać tylko interfejsy przez interfejsy, ale w rzeczywistości interfejs może rozszerzać typ:

type Basic = { flag: boolean }; interface Extra extends Basic { name: string; }

Natomiast typy nie mogą być rozszerzane przez extends inne typy — tylko przez przecięcie typów (&).

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


Historia

W jednym dużym projekcie łączono interfejsy przez extends, zapominając, że identyczne właściwości muszą zgadzać się co do typu. Kiedy ktoś zmienił typ właściwości w interfejsie rodzicu, w interfejsach potomnych pojawiły się silent-konflikty, baza przestała odpowiadać API.

Historia

W bibliotece napisano aliasy typów z nakładaniem właściwości przez & (przecięcia), ale niektóre właściwości uczynili niezgodnymi co do typu. TypeScript przepuścił to na etapie kompilacji, ale w rzeczywistości w czasie działania systemy pojawiły się nieokreślone pola.

Historia

Zespół uważał, że interfejsu nie można rozszerzać typem, i dla rozszerzenia ogólnej funkcjonalności przepisywał wszystkie struktury z type na interface, tracąc dużo czasu i wysiłku — chociaż można było po prostu rozszerzać istniejące typy w niestandardowy sposób.