Mulți dezvoltatori sunt confuzi atunci când aleg între o interfață TypeScript și un tip. Acest lucru se datorează, probabil, faptului că sunt foarte asemănătoare, cu diferențe minore.
Să explorăm câteva practici sensibile și valori implicite, în timp ce descoperim câteva pietre ascunse în limbajul TypeScript și să răspundem la întrebarea „Ar trebui să folosesc o interfață sau un tip?”
După ce ați terminat, consultați celălalt articol al meu despre TypeScript Interfaces vs Classes!
Iată regula mea: Pentru cazuri de utilizare, cum ar fi crearea de noi tipuri prin lucruri precum primitive, tipuri de uniune și tipuri de tuplu, prefer să folosesc cuvântul cheie type
. Pentru orice altceva (obiecte/rețele), este un interface
.
Un interface
este extrem de util atunci când se lucrează cu structuri de date, deoarece sunt o reprezentare foarte vizuală (deși la fel este și type
, aceasta este de obicei preferința mea). Este complet în regulă să alegeți un type
și pentru obiectele și array-urile dvs. de asemenea.
Cu toate acestea, haideți să descoperim ceva mai multe despre Tipuri vs Interfețe în TypeScript, astfel încât să puteți lua o decizie mai informată.
Obiecte: Tip vs. Interfață
În mod normal, am defini o structură de date pentru a modela un tip în raport cu variabilele și argumentele funcțiilor noastre intenționate. De cele mai multe ori o structură de date este o matrice sau un obiect care ar putea conține câteva metode.
Să creăm un obiect ca o interfață (abordare recomandată):
interface Milkshake { name: string; price: number; getIngredients(): string;}
Aici, prefer să folosesc o interfață pentru că este clar că este o interfață și nu o variabilă cu date alocate – un câștig frumos de lizibilitate. Folosim name
și price
pentru a permite setarea înregistrărilor și getIngredients
ca apel de metodă.
🎉 Descarcă-l gratuit!
Sunteți gata să mergeți dincolo de ForEach? Încredeți-vă în metodele avansate – Reduce, Find, Filter, Every, Some și Map.
- Înțelegeți pe deplin cum să gestionați structurile de date JavaScript cu operații imuabile
- 31 de pagini de sintaxă aprofundată, exemple din lumea reală, sfaturi și trucuri
- Scrieți o logică de programare mai curată și mai bine structurată în 3 ore
Ca un bonus suplimentar, vă vom trimite, de asemenea, câteva bunătăți suplimentare prin câteva e-mailuri suplimentare.
Când comparăm asta cu un tip – ar putea fi ușor confundat cu un obiect real datorită atribuirii =
:
type Milkshake = { name: string; price: number; getIngredients(): string;};
Este doar mica mea preferință pentru a alege un interface
în locul folosirii unui type
aici – dar sunteți liberi să folosiți cuvântul cheie type
dacă doriți.
Intersecție: Tip vs. interfață
Intersectarea înseamnă pur și simplu să combini unul sau mai multe tipuri! Acest model poate fi realizat folosind atât un interface
, cât și un type
.
Să presupunem următoarele interfețe, vă voi arăta cum putem intersecta un interface
și un type
:
interface MilkshakeProps { name: string; price: number;}interface MilkshakeMethods { getIngredients(): string;}
Cu o interfață, ne vom intersecta folosind cuvântul cheie extends
. Folosesc mai multe interfețe pentru a vă arăta cum să extindem (moștenim) într-o interfață finală Milkshake
care conține toate proprietățile și metodele definite în altă parte:
// { name: string, price: number, getIngredients(): string }interface Milkshake extends MilkshakeProps, MilkshakeMethods {}
Acum putem folosi Milkshake
oriunde dorim și putem beneficia de faptul că avem name
, price
și getIngredients
într-o singură referință de interfață.
Iată cum am face același lucru cu un type
și intersectând tipurile prin &
:
// { name: string, price: number, getIngredients(): string }type Milkshake = MilkshakeProps & MilkshakeMethods;
Vă recomand să folosiți un type
în loc de un interface
atunci când doriți să intersectați tipuri. Folosind extends
se simte un pic mai verbos și nu la fel de clar de citit și simt că pentru asta a fost făcut cuvântul cheie type
.
Este, de asemenea, super ușor să combini mai multe tipuri cu type
. Mi se pare că codul este mai clar decât folosind extends
cu interfețe.
Interfețele sunt, de asemenea, limitate – aliasul type
poate fi folosit pentru tipuri mai complexe, cum ar fi tupluri, primitive, uniuni și altele:
// { name: string, price: number, getIngredients(): string }type Milkshake = MilkshakeProps & { getIngredients(): string };
Primitive: Tip vs. interfață
Să vorbim despre tipurile primitive. Da, șiruri de caractere, numere etc. Puteți atribui un tip primitiv doar unui alias type
:
type MilkshakeName = string;interface Milkshake { name: MilkshakeName; price: number;}
Dacă trebuie să folosiți un primitiv, folosiți un type
. Interfețele sunt de negăsit aici pentru o singură valoare, deoarece sintaxa nu le acceptă.
🎉 Descarcă-l gratuit!
Sunteți gata să mergeți dincolo de ForEach? Încredeți-vă în metodele avansate – Reduce, Find, Filter, Every, Some și Map.
- Înțelegeți pe deplin cum să gestionați structurile de date JavaScript cu operații imuabile
- 31 de pagini de sintaxă aprofundată, exemple din lumea reală, sfaturi și trucuri
- Scrieți o logică de programare mai curată și mai bine structurată în 3 ore
Ca un bonus suplimentar, vă vom trimite, de asemenea, câteva bunătăți suplimentare prin câteva e-mailuri suplimentare.
Pentru majoritatea cazurilor însă, ar fi mai ușor să folosiți direct valoarea primitivă:
interface Milkshake { name: string; price: number;}
Nu vă complicați prea mult codul!
Clasi: Tip vs. interfață
Dacă ați ales un type
sau interface
, modul în care îl folosim cu o clasă este același:
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 ; }}
Classele nu suportă implementarea/extinderea tipurilor de uniune, deoarece acestea sunt considerate a fi planuri statice. Acest lucru înseamnă că trebuie să fiți super explicit cu privire la fiecare tip pe care îl implementați, deoarece nu poate fi dinamic sau să se schimbe în acest moment din cauza limitărilor TypeScript.
Aflați mai multe despre TypeScript Interfaces vs Classes!
Funcții: Tip vs Interfață
În mod normal aș crea o funcție folosind aliasul type
deoarece de cele mai multe ori am dori să scriem o funcție anonimă:
type IngredientsFn = () => string;const getIngredients: IngredientsFn = () => ;
Dar, dacă folosirea unui interface
pentru acest lucru ar fi mai mult în stilul tău, iată cum să faci asta:
interface IngredientsFn { () => string;}
Se simte un pic ciudat în comparație cu utilizarea type
, dar, din nou, ambele sunt TypeScript complet valabile și nu există nicio diferență atunci când codul este compilat.
Când să nu folosiți un tip
Acum am explorat diferitele comparații și abordări recomandate, este timpul să vorbim despre Declaration Merging, o caracteristică din TypeScript care se aplică doar la interface
și ar fi un motiv pentru a alege un interface
în locul unui type
.
Pentru a fuziona tipurile folosind type
, ar trebui să facem ceva de genul acesta și să creăm un nou type
final:
type MilkshakeProps = { name: string; price: number;};type MilkshakeMethods = { getIngredients(): string;};type Milkshake = MilkshakeProps & MilkshakeMethods;
Nostru type Milkshake
este acum un alias de tip al lui MilkshakeProps
și MilkshakeMethods
. Rețineți că, pentru a obține acest comportament, a trebuit să creăm Milkshake
, ceea ce ne oferă 3 alias-uri de tip individuale.
În cazul interfețelor, există de fapt o abordare mai inteligentă (unii ar putea spune un pic prea inteligentă) numită „declaration merging”.
Potem realiza o fuziune de declarații prin simpla declarare a aceluiași interface
de două ori în același domeniu de aplicare (acest lucru ar putea fi fie prin importarea interfeței dintr-un alt modul, fie prin declararea ei la nivel local alături de o altă interfață):
// 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 conține acum name
, price
și getIngredients
! Cu toate acestea, este fuziunea declarațiilor un lucru bun? Sincer, nu sunt un fan și am impresia că ar putea duce la mai mult rău decât bine. Aș compune tipurile dvs. prin type
mai degrabă decât să folosesc fuziunea declarațiilor – dar cel puțin acum cunoașteți principala (principalele) diferență(e).
Concluzie
Așa că iată-l! Principalele diferențe dintre Tipuri și Interfețe în TypeScript.
Pentru a recapitula, cu câteva preferințe personale de asemenea, aș rămâne cu un interface
pentru obiecte și aș folosi cuvântul cheie alias type
pentru a compune noi tipuri din mers. Aceste noi tipuri ar putea fi chiar din interfețe sau alte tipuri, cum ar fi tupluri, uniuni și tipuri de intersecție. Există o mulțime de posibilități, dar înțelegând abordările putem începe să alegem instrumentul potrivit.
În cea mai mare parte, interfețele și tipurile sunt cam la fel, în afară de câteva diferențe acoperite aici. Sper că v-a făcut plăcere să citiți!
Dacă sunteți serioși în ceea ce privește abilitățile dumneavoastră TypeScript, următorul pas este să aruncați o privire la cursurile mele TypeScript, acestea vă vor învăța în detaliu toate elementele de bază ale limbajului, precum și multe cazuri de utilizare avansată de care veți avea nevoie în dezvoltarea TypeScript de zi cu zi!
Codificare fericită!