PorównaniePorównania

interface vs type

interface opisuje kształt obiektu i można go rozszerzać oraz łączyć z inną deklaracją o tej samej nazwie, a type to alias dla dowolnego typu, także unii i krotek.

Na tej stronie

Porównanie w tabeli

#
  • Co opisuje

    interface
    Kształt obiektu: pola i metody
    type
    Dowolny typ, np. obiekt, unię, krotkę, funkcję
  • Rozszerzanie

    interface
    Słowem extends
    type
    Przecięciem &
  • Dwie deklaracje o tej samej nazwie

    interface
    Łączą się w jedną (merging)
    type
    Błąd: Duplicate identifier 'Nazwa'
  • Unie i krotki

    interface
    Nie da się wyrazić
    type
    Podstawowe zastosowanie
  • Implementacja przez klasę (`implements`)

    type
    Tak, jeśli alias opisuje obiekt
  • Typowe użycie

    interface
    Obiekty, kontrakty klas, publiczne API bibliotek
    type
    Unie, krotki, typy funkcji, wyniki typów narzędziowych

Przykład

#
TypeScript
interface CourseInterface {
  title: string
  modules: number
}

type CourseType = {
  title: string
  modules: number
}

type Difficulty = 'easy' | 'medium' | 'hard'

const html: CourseInterface = { title: 'HTML i CSS', modules: 11 }
const python: CourseType = { title: 'Python', modules: 12 }
const level: Difficulty = 'medium'

console.log(html.title, python.modules, level)
Wynik
HTML i CSS 12 medium

Definicja i zastosowanie

#

Obie konstrukcje nadają nazwę kształtowi obiektu i w większości przypadków możesz użyć jednej albo drugiej. Kompilator sprawdza je tak samo: obiekt jest zgodny z typem, jeśli ma wymagane pola o właściwych typach, niezależnie od tego, czy kształt opisano przez interface, czy przez type.

Różnice widać przy rozszerzaniu i przy typach, które nie są obiektami. Interfejs rozszerzasz słowem extends i możesz dopisać do niego pola drugą deklaracją o tej samej nazwie, bo deklaracje się łączą. Alias type rozszerzasz przecięciem &, a dwie deklaracje o tej samej nazwie to błąd kompilacji. Tylko type opisze unię, krotkę czy typ funkcji, bo interface wyraża wyłącznie kształt obiektu.

Do obiektów i kontraktów klas naturalnym wyborem jest interface, zwłaszcza w bibliotekach, gdzie przydaje się łączenie deklaracji. Do unii, krotek, typów funkcji i wyników typów narzędziowych potrzebny jest type. Wiele zespołów ustala prostą zasadę: obiekty przez interface, wszystko inne przez type.

Składnia

#
Składnia
interface Nazwa {
  pole: typ
}

type Nazwa = typ

Więcej przykładów

#
Łączenie deklaracji działa tylko dla interface
TypeScript
interface Config {
  darkMode: boolean
}

interface Config {
  fontSize: number
}

const config: Config = { darkMode: true, fontSize: 16 }
console.log(Object.keys(config))
Wynik
['darkMode', 'fontSize']
type nie da się otworzyć drugą deklaracją
TypeScript
type Profile = { name: string }
type Profile = { age: number }
// Błąd: Duplicate identifier 'Profile'.
Tylko type wyrazi unię i krotkę
TypeScript
type Pair = [string, number]
type Status = 'draft' | 'published'

const [title, exp]: Pair = ['Flexbox', 20]
const status: Status = 'draft'

console.log(title, exp, status)
Wynik
Flexbox 20 draft

Dobre praktyki

#
  • Jeśli potrzebujesz tylko kontraktu bez implementacji, pamiętaj, że klasa abstrakcyjna to inne narzędzie: interfejs nie zawiera kodu, klasa abstrakcyjna może.
  • Nazywaj interfejsy od tego, czym obiekt jest (User, Course), bez przedrostka I.
  • Ustal w projekcie jedną konwencję dla zwykłych obiektów, żeby nie zastanawiać się przy każdej deklaracji.

Powiązane hasła

#

Widzisz błąd albo brakuje przykładu? Napisz do nas.