Razlika između 'type' i 'interface' u TypeScriptu
Tags: webdev, javascript, react, typescript
Published: 2024-04-13 12:52:47

## 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/63d03rht5xgiw6ycqh8e.png)


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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kgd0m2fn7v9imsu7psit.png)
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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4j3wiw0y0jei9i2sv5aw.png)


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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g07sc9l7g8qlmvq9vy05.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eibtcmgge5kyxvfqewxv.png)

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


![define a primitive with type alias](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/beie43d70n5xsv3536we.png)
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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j7rpi93td26rblz1dxe4.png)

---

#### 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ewfkroc9xs7qjz6lsotc.png)

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


![interface with utility types in ts](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yoyt0978e03x9f1ohk83.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7tb2qi9ylcd05orube7j.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s43ldz1h7wd2n0ci8z0k.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wwsus0gmxpwake1th27q.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qrfg37t0c75w2fewip1l.png)

Klasu je najnormalnije moguće definisati sa tipom.


![class with type example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ecyi87pkpoq44lx7ocp3.png)

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.