Wielu programistów jest zdezorientowanych przy wyborze między interfejsem TypeScript a typem. Dzieje się tak prawdopodobnie dlatego, że są one bardzo podobne z niewielkimi różnicami.
Poznajmy kilka rozsądnych praktyk i domyślnych rozwiązań, jednocześnie odkrywając kilka ukrytych klejnotów w języku TypeScript i odpowiedzmy na pytanie „Czy powinienem używać interfejsu czy typu?”
Jak już skończysz, sprawdź mój inny artykuł na temat TypeScript Interfaces vs Classes!
Oto moja zasada: Dla przypadków użycia, takich jak tworzenie nowych typów poprzez rzeczy takie jak prymitywy, typy unii i typy tuple, wolę używać słowa kluczowego type
. Dla wszystkiego innego (obiekty/tarcze), jest to interface
.
Słowo interface
jest niezwykle pomocne, gdy mamy do czynienia ze strukturami danych, ponieważ są one bardzo wizualną reprezentacją (aczkolwiek tak samo jak type
, jest to zazwyczaj moja preferencja). Jest to całkowicie w porządku, aby wybrać type
dla swoich obiektów i tablic również.
Niemniej jednak, odkryjmy trochę więcej o Typach vs Interfejsach w TypeScript, abyś mógł podjąć bardziej świadomą decyzję.
Obiekty: Typ vs Interfejs
Typowo zdefiniowalibyśmy strukturę danych do modelowania typu względem naszych zamierzonych zmiennych i argumentów funkcji. Najczęściej struktura danych jest tablicą lub obiektem, który może zawierać kilka metod.
Utwórzmy obiekt jako interfejs (zalecane podejście):
interface Milkshake { name: string; price: number; getIngredients(): string;}
W tym przypadku wolę używać interfejsu, ponieważ jest jasne, że jest to interfejs, a nie zmienna z przypisanymi danymi – miłe zwycięstwo czytelności. Używamy name
i price
, aby umożliwić ustawianie rekordów i getIngredients
jako naszego wywołania metody.
🎉 Pobierz za darmo!
Gotowy, aby wyjść poza ForEach? Zdobądź pewność siebie dzięki zaawansowanym metodom – Reduce, Find, Filter, Every, Some i Map.
- W pełni zrozum, jak zarządzać strukturami danych JavaScript z niezmiennymi operacjami
- 31 stron składni dogłębnej, rzeczywistych przykładów, wskazówek i trików
- Napisz czystszą i lepiej zorganizowaną logikę programowania w ciągu 3 godzin
Jako dodatkowy bonus, wyślemy Ci również kilka dodatkowych smakołyków przez kilka dodatkowych e-maili.
Gdy porównamy to z typem – może być łatwo pomylone jako rzeczywisty obiekt z powodu przypisania =
:
type Milkshake = { name: string; price: number; getIngredients(): string;};
To jest tylko moja mała preferencja do wyboru interface
nad użyciem type
tutaj – ale możesz swobodnie używać słowa kluczowego type
, jeśli chcesz.
Intersecting: Type vs Interface
Intersecting oznacza po prostu łączenie jednego lub więcej typów! Ten wzorzec może być osiągnięty przy użyciu zarówno interface
jak i type
.
Załóżmy następujące interfejsy, pokażę ci jak możemy przecinać interface
i type
:
interface MilkshakeProps { name: string; price: number;}interface MilkshakeMethods { getIngredients(): string;}
Z interfejsem, przecinalibyśmy używając słowa kluczowego extends
. Używam wielu interfejsów, aby pokazać, jak rozszerzyć (dziedziczyć) do ostatecznego interfejsu Milkshake
zawierającego wszystkie właściwości i metody zdefiniowane gdzie indziej:
// { name: string, price: number, getIngredients(): string }interface Milkshake extends MilkshakeProps, MilkshakeMethods {}
Możemy teraz używać Milkshake
gdziekolwiek chcemy i możemy korzystać z posiadania name
, price
i getIngredients
w jednym odwołaniu do interfejsu.
Oto jak zrobilibyśmy to samo używając type
i przecinając typy przez &
:
// { name: string, price: number, getIngredients(): string }type Milkshake = MilkshakeProps & MilkshakeMethods;
Zalecałbym używanie type
zamiast interface
, gdy chcesz przecinać typy. Użycie extends
jest nieco bardziej czasochłonne i nie tak jasne do odczytania, a czuję, że to jest to, do czego słowo kluczowe type
zostało stworzone.
Jest to również bardzo proste, aby po prostu połączyć więcej typów z type
. Uważam, że kod jest bardziej przejrzysty niż używanie extends
z interfejsami.
Interfejsy są również ograniczone – alias type
może być używany do bardziej złożonych typów, takich jak tuple, prymitywy, związki i inne więcej:
// { name: string, price: number, getIngredients(): string }type Milkshake = MilkshakeProps & { getIngredients(): string };
Primitives: Type vs Interface
Porozmawiajmy o typach prymitywnych. Tak, ciągi znaków, liczby itd. Możesz przypisać typ prymitywny tylko do aliasu type
:
type MilkshakeName = string;interface Milkshake { name: MilkshakeName; price: number;}
Jeśli musisz użyć prymitywu, użyj type
. Interfejsy nie są tutaj dobrym rozwiązaniem dla pojedynczej wartości, ponieważ składnia ich nie obsługuje.
🎉 Pobierz za darmo!
Gotowy, aby wyjść poza ForEach? Zdobądź pewność siebie dzięki zaawansowanym metodom – Reduce, Find, Filter, Every, Some i Map.
- W pełni zrozum, jak zarządzać strukturami danych JavaScript z niezmiennymi operacjami
- 31 stron składni dogłębnej, rzeczywistych przykładów, wskazówek i trików
- Napisz czystszą i lepiej zorganizowaną logikę programowania w ciągu 3 godzin
Jako dodatkowy bonus, wyślemy Ci również kilka dodatkowych smakołyków w kilku dodatkowych e-mailach.
W większości przypadków jednak, łatwiej byłoby po prostu użyć wartości prymitywnej bezpośrednio:
interface Milkshake { name: string; price: number;}
Nie komplikuj nadmiernie swojego kodu!
Klasy: Type vs Interface
Czy wybrałeś type
czy interface
sposób, w jaki używamy go z klasą, jest taki sam:
type Size = { size: string};interface Milkshake { name: string; price: number; getIngredients(): string;}class Order implements Size, Milkshake { // Size size = 'large'; // Milkshake name = 'Vanilla'; price = 399; getIngredients() { return ; }}
Klasy nie obsługują implementacji/rozszerzania typów unii, ponieważ są uważane za statyczne blueprints. Oznacza to, że musisz być bardzo dokładny w każdym typie, który implementujesz, ponieważ nie może on być dynamiczny lub zmieniać się teraz z powodu ograniczeń TypeScript.
Dowiedz się więcej o TypeScript Interfaces vs Classes!
Funkcje: Type vs Interface
Typowo utworzyłbym funkcję przy użyciu aliasu type
, ponieważ przez większość czasu chcielibyśmy wpisać anonimową funkcję:
type IngredientsFn = () => string;const getIngredients: IngredientsFn = () => ;
Jednakże, jeśli użycie interface
do tego byłoby bardziej w twoim stylu, oto jak to zrobić:
interface IngredientsFn { () => string;}
To po prostu czuje się trochę wonky w porównaniu do używania type
, ale znowu oba są całkowicie poprawne TypeScript i nie ma różnicy, gdy kod jest skompilowany.
Kiedy nie używać typu
Teraz zbadaliśmy różne porównania i zalecane podejścia, nadszedł czas, aby porozmawiać o scalaniu deklaracji, funkcji w TypeScript, która ma zastosowanie tylko do interface
i byłaby powodem, aby wybrać interface
zamiast type
.
Aby scalić typy używając type
, musielibyśmy zrobić coś takiego i stworzyć nową finalną type
:
type MilkshakeProps = { name: string; price: number;};type MilkshakeMethods = { getIngredients(): string;};type Milkshake = MilkshakeProps & MilkshakeMethods;
Nasz type Milkshake
jest teraz aliasem typu MilkshakeProps
i MilkshakeMethods
. Zauważ, że aby osiągnąć takie zachowanie, musieliśmy stworzyć Milkshake
, co daje nam 3 indywidualne aliasy typu.
W przypadku interfejsów, istnieje w rzeczywistości mądrzejsze podejście (niektórzy mogą powiedzieć, że nieco zbyt mądre) zwane łączeniem deklaracji.
Możemy osiągnąć scalenie deklaracji przez proste zadeklarowanie tego samego interface
dwa razy w tym samym zakresie (może to być albo przez import interfejsu z innego modułu, albo zadeklarowanie go lokalnie obok innego interfejsu):
// declared once...interface Milkshake { name: string; price: number;}// declared again the same, it works!interface Milkshake { getIngredients(): string;}// { name: string, price: number, getIngredients(): string }const milkshake: Milkshake = { name: 'Banana', price: 399, getIngredients() {...}};
Milkshake zawiera teraz name
, price
i getIngredients
! Jednakże, czy łączenie deklaracji to dobra rzecz? Szczerze mówiąc, nie jestem fanem i czuję, że może to prowadzić do więcej szkody niż pożytku. Ja bym raczej skomponował twoje typy poprzez type
niż używał łączenia deklaracji – ale przynajmniej znasz teraz główną różnicę(y).
Wniosek
Więc masz to! Główne różnice między typami i interfejsami w TypeScript.
Podsumowując, z pewnymi osobistymi preferencjami również, trzymałbym się interface
dla obiektów i używałbym słowa kluczowego type
alias do komponowania nowych typów w locie. Te nowe typy mogłyby nawet pochodzić z interfejsów lub innych typów, takich jak tuple, związki i typy przecięcia. Jest wiele możliwości, ale poprzez zrozumienie podejścia możemy zacząć wybierać odpowiednie narzędzie.
W większości przypadków interfejsy i typy są całkiem takie same, poza kilkoma różnicami, które zostały tutaj omówione. Mam nadzieję, że podobało ci się czytanie!
Jeśli poważnie myślisz o swoich umiejętnościach w zakresie TypeScript, następnym krokiem jest zapoznanie się z moimi kursami TypeScript, które szczegółowo nauczą cię podstaw języka, jak również wielu zaawansowanych przypadków użycia, których będziesz potrzebował w codziennym rozwoju TypeScript!
Szczęśliwego kodowania!