Razlika između 'type' i 'interface' u TypeScriptu

bslaven

Slaven Bunijevac

Posted on April 13, 2024

Razlika između 'type' i 'interface' u TypeScriptu

TypeScript je sjajan alat koji donosi nove mogućnosti, koje ne postoje u JavaScriptu. Glavna stvar koju TypeScript razlikuje od JavaScripta je to što možemo definisati tipove podataka sa kojim radimo.

Jedan od načina da se definiše tip podataka je korištenje tipa, odnosno type aliasa, a drugi je korištenje interfejsa, odnosno interface. Upravo razlika između ova dva načina je tema ovog teksta.


Uvod

U ovom uvodu ću da postavim osnovno okruženje i kontekst koji će biti isti za sve sljedeće primjere, da se ne bi ponavljao u narednim poglavljima.

Recimo na primjer da imam neku komponentu User koja će dobiti podatke o korisniku u props objektu koji ćemo prema TypeScript konvenciji opisati/definisati sa UserProps.

react component with ts props example

Ako pokušam da opišem objekat sa UserProps, a taj UserProps ne postoji nigdje TypeScript će me upozoriti.


Osnovna sintaksa

Postoje dvije osnovne sintaksičke razlike. Tip koristi ključnu riječ type, a interfejs interface.

Basic example of types and interfaces
Druga razlika je što tip koristi znak jednakosti, a interfejs ne koristi.

U narednim primjerima ću nazive tipova počinjati sa slovom 'T', a interfejse sa slovom 'I'. Ovo se može pronaći negdje kao konvencija, ali nije neophodno raditi.


Proširivanje i naslijeđivanje

Recimo na primjer da imam nekog korisnika kog sam definisao preko tipa kao TUserProps, ali kasnije dodajem definiciju za administratora koji ima sva svojstva kao i korisnik, plus još neka.

ts type intersection example

Kod tipova se ovo zove ukrštanje ili preklapanje (ENG: 'intersection'), odnosno dva tipa se preklapaju po nekim svojstvima. Znak ampersand ('&') sam iskoristio da spojim već definisani TUserProps i nova svojstva koja želim da dodati administratoru.

Interfejs sa druge strane koristi ključnu riječ extends da spoji dvije definicije. Ova sintaksa će biti poznata ljudima koji koriste klase u JavaScriptu/TypeScriptu.

ts interface extends example

Kod interfejsa se ova tehnika zove naslijeđivanje. Dakle, objekat IAdminProps će naslijediti sva svojstva koja postoje u objektu IUserProps ime i godine, pa sam mu dodao ulogu.


Objekti i sve ostalo

Interfejsom se mogu definisati samo objekti, dok se tipom mogu definisati objekti, ali i sve ostalo.

Ako želim da definišem objekat mogu koristiti interfejs ili tip.

interface example to create an object in ts

Međutim, ako želim da definišem bilo šta drugo moram koristiti tip.

define a primitive with type alias
Nije moguće koristiti interfejs za definisanje primitivnih tipova.


Unije

Tipove je moguće koristiti da definisanje unija (skupova). Lako se može dogoditi na primjer da želimo da pohranimo neku primitivnu vrijednost, ali i da eventualno pratimo niz takvih vrijednosti.

types with unions example


Utility tipovi

U TypeScriptu postoje 'utility' tipovi koji nam omogućuju neke posebne funkcionalnosti. Recimo da npr. želim da iskoristim Omit utility tip kako bi izostavio neko svojstvo objekta.

Sa type aliasom bi to izgledalo ovako.

type alias with utility types

Ovo je tehnički moguće uraditi i sa interfejsom, ali uz mnogo ružniju sintaksu.

interface with utility types in ts

Morao sam iskoristiti ključnu riječ extends, a morao sam staviti i prazne vitičaste zagrade na kraju deklaracije.


Tuple

Tupl (ENG. Tuple) je specijalna vrsta niza u TypeScriptu. To je niz koji ima fiksno definisanu dužinu. Dužina tupla se ne može naknadno mijenjati.

Ako bi želio definisati neki tip kao tupl preko type aliasa, to je lako uraditi.

example of defining tuples with interfaces and types

Kao što se vidi iz primjera korištenje interfejsa je mnogo obimnije i teže za čitanje. Tip je za ove situacije mnogo bolje rješenje.


Izvlačenje

Tip se može iskoristiti da se izvuče neka struktura iz objekta. Recimo na primjer da imam neki objekat stan. Ako želim da izvučem npr. svojstvo 'specifikacije' iz tog objekta tip je sjajno rješene.

extraction with type alias in typescript

Iskoristio sam svojstvo iz objekta kako bi definisao tip.

Ovo je moguće i sa interfejsom, ali kao što se vidi iz primjera sa unijama i tuplovima mora se koristiti ključna riječ extends, tako da je pristup sa tipovima mnogo bolji.


Spajanje i ponovna deklaracija

Jedna od situacija na koje se sasvim realno može naići je da se na projektu nađu definisane dvije strukture sa istim imenom. Ako se to dogodi sa interfejsom one će jednostavno biti spojene.

Image description

Kao što se vidi u primjeru sva svojstva iz svakog interfejsa su obavezna u novom objektu user. Ovo može biti korisno, ako se na primjer koristi neka biblioteka iz koje dobijamo neki interfejs, pa želimo da ga proširimo.

Međutim, može biti i veoma loše jer lako može doći do neželjenih izmjena interfejsa.

Sa tipovima ovo nije moguće. TypeScript će odmah izbaciti grešku ukoliko se pojave dva tipa sa istim nazivom.


Klase

Postoji jedno pogrešno mišljenje na koje se može naići kada se radi sa TypeScriptom, a to je da je klase moguće opisati/definisati samo pomoću interfejsa.

class with interfase example

Klasu je najnormalnije moguće definisati sa tipom.

class with type example

Bilo koja od ove dvije opcije je validna.

Ukratko

  • Interfejs može definisati samo objekte, tip može objekte i sve ostalo.

  • Sintaksa za proširivanje, unije, utility tipove je mnogo bolja ako se koristi type alias.

  • Interfejsi su otvoreni i podložni neželjenim izmjenama, dok su tipovi zatvoreni.

  • Nije tačno da se klase mogu definisati samo pomoću interfejsa. Klase bez problema mogu biti definisane tipom.

💖 💪 🙅 🚩
bslaven
Slaven Bunijevac

Posted on April 13, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related