O mnieBlogGitHub

Ciekawostki Typescript #1 - typ vs. interfejs

01 September, 2020 - 2 min read

W TypeScripcie mamy do dyspozycji dwa podobne byty, które przy deklarowaniu typów wydają się być zamienne - type oraz interface. Czy te dwa typy czymś się różnią?

type Person1 = {
  name: string
}

interface Person2 {
  name: string
}

W ogólności, poza subtelną różnicą w składni - do type "przypisujemy" deklarację, a interface deklarujemy wprost, bez znaku = - te dwie konstrukcje można stosować zamiennie. Obie będą weryfikować typ, np.:

const alice: Person1 = {
  name: "Alice",
  age: 20,
  // -> tu będzie błąd
}

const bob: Person1 = {
  name: "Bob",
  age: 25,
  // -> tu będzie błąd
}

Obie konstrukcje możemy też używać zamiennie w bardziej złożonych przykładach, jak sygnatury indeksu czy typy funkcji, np.:

type Dictionary1 = { [key: string]: string }
interface Dictionary2 {
  [key: string]: string
}

Zarówno typ, jak i interfejs możemy "podziedziczyć" (właściwe określenie w świecie TS to raczej - rozszerzyć):

class Employee1 implements Person1 {
  name: string
}

class Employee2 implements Person2 {
  name: string
}

Jakie zatem mamy różnice?

  1. Jeśli definiujemy unię, to możemy zastosować tylko tylko type: type State = 'on' | 'off'
  2. Tylko type może rozszerzać unię: type StateExtended = State & 'paused'
  3. Teoretycznie interfejsem można wyrazić krotkę, ale za pomocą typu jest to dużo bardziej czytelne i naturalne:
type Pair = [number, number]

// zamiast jakiegoś dziwadła

interface Tuple {
  0: number
  1: number
  length: 2
}
  1. Z drugiej strony interface umożliwia scalanie deklaracji, czyli coś w stylu partial class z C#. Chodzi o to, że możemy w jednym pliku zadeklarować interfejs, a w innym - "dalszą jego część", finalnie uzyskując interfejs, który będzie połączeniem obydwu deklaracji, np.:
// plik Person.ts
interface Person {
  name: string
}

// plik PersonAddress.ts
interface Person {
  address: string
}

Ten myk nie jest potrzebny raczej w naszym kodzie (możemy przecież scalić deklaracje do jednego pliku), ale przydaje się, gdy chcemy zmodyfikować typ, który dostajemy z jakiejś zewnętrznej biblioteki. Ten mechanizm wykorzystuje też podstawowa biblioteka TS - nowości i zmiany w kolejnych standardach ES to kolejne pliki, które rozszerzają wcześniejsze deklaracje: zatem wybierając odpowiedni standard ES, de facto wybieramy zestaw plików z deklaracjami, które są scalane.

Ten wpis jest częścią serii o TypeScripcie, inspirowaną lekturą książki D. Vanderkama pt. "TypeScript. Skuteczne programowanie".

© 2020, Built with Gatsby