Veel ontwikkelaars zijn in de war als ze moeten kiezen tussen een TypeScript-interface of een type. Dit komt waarschijnlijk omdat ze erg op elkaar lijken met kleine verschillen.
Laten we een aantal verstandige praktijken en standaards verkennen, terwijl we een aantal verborgen juweeltjes in de TypeScript taal blootleggen en de vraag beantwoorden “Moet ik een interface of een type gebruiken?”
Als je klaar bent, bekijk dan mijn andere artikel over TypeScript Interfaces vs Classes!
Hier is mijn regel: Voor het maken van nieuwe types met behulp van primitieven, union types en tuple types, gebruik ik liever het type
keyword. Voor al het andere (objecten/arrays), is het een interface
.
Een interface
is zeer nuttig bij het omgaan met datastructuren, omdat ze een zeer visuele weergave zijn (hoewel type
dat ook is, dit is typisch mijn voorkeur). Het is ook prima om een type
te kiezen voor je objecten en arrays.
Niettemin, laten we wat meer ontdekken over Types vs Interfaces in TypeScript, zodat je een beter geïnformeerde beslissing kunt nemen.
Objects: Type vs Interface
Typisch zouden we een data structuur definiëren om een type te modelleren tegen onze bedoelde variabelen en functie argumenten. Meestal is een datastructuur een array of een object dat een paar methoden kan bevatten.
Laten we een object maken als een interface (aanbevolen aanpak):
interface Milkshake { name: string; price: number; getIngredients(): string;}
Hier geef ik de voorkeur aan het gebruik van een interface omdat het duidelijk is dat het een interface is en niet een variabele met toegewezen gegevens – een mooie leesbaarheidswinst. We gebruiken name
en price
om records in te kunnen stellen en getIngredients
als onze methode-aanroep.
🎉 Download het gratis!
Klaar om verder te gaan dan ForEach? Krijg vertrouwen met geavanceerde methoden – Reduce, Find, Filter, Every, Some en Map.
- Begrijp volledig hoe JavaScript Data Structuren te beheren met onveranderlijke operaties
- 31 pagina’s met diepgaande syntaxis, real-world voorbeelden, tips en trucs
- Schrijf schonere en beter gestructureerde programmeer logica binnen 3 uur
Als extra bonus, sturen we u ook nog wat extra goodies via een paar extra e-mails.
Wanneer we dat vergelijken met een type – het zou gemakkelijk kunnen worden verward als een echt object als gevolg van de toewijzing =
:
type Milkshake = { name: string; price: number; getIngredients(): string;};
Dit is slechts mijn kleine voorkeur voor het kiezen van een interface
boven het gebruik van een type
hier – maar je bent vrij om het type
sleutelwoord te gebruiken als je dat wilt.
Intersecting: Type vs Interface
Intersecten betekent simpelweg het combineren van een of meer types! Dit patroon kan worden bereikt met behulp van zowel een interface
of type
.
Laten we uitgaan van de volgende interfaces, ik zal u laten zien hoe we een interface
en type
kunnen doorsnijden:
interface MilkshakeProps { name: string; price: number;}interface MilkshakeMethods { getIngredients(): string;}
Met een interface, zouden we doorsnijden door gebruik te maken van het extends
sleutelwoord. Ik gebruik meerdere interfaces om te laten zien hoe we kunnen uitbreiden (overerven) naar een uiteindelijke Milkshake
interface die alle elders gedefinieerde eigenschappen en methoden bevat:
// { name: string, price: number, getIngredients(): string }interface Milkshake extends MilkshakeProps, MilkshakeMethods {}
We kunnen Milkshake
nu overal gebruiken waar we maar willen en kunnen profiteren van het feit dat name
, price
en getIngredients
in slechts één interfaceverwijzing staan.
Hier ziet u hoe we hetzelfde zouden doen met een type
en het doorsnijden van de types via &
:
// { name: string, price: number, getIngredients(): string }type Milkshake = MilkshakeProps & MilkshakeMethods;
Ik zou aanraden een type
te gebruiken in plaats van een interface
wanneer u types wilt doorsnijden. Het gebruik van extends
voelt een beetje meer omslachtig en niet zo duidelijk om te lezen en ik heb het gevoel dat dit is waar het type
sleutelwoord voor gemaakt is.
Het is ook super eenvoudig om gewoon meer types te combineren met type
. Ik vind de code duidelijker dan extends
met intefaces.
Interfaces zijn ook beperkt – de type
alias kan worden gebruikt voor complexere types zoals tuples, primitives, unions en andere meer:
// { name: string, price: number, getIngredients(): string }type Milkshake = MilkshakeProps & { getIngredients(): string };
Primitives: Type vs Interface
Laten we het eens hebben over primitieve types. Ja, strings, getallen enz. U kunt een primitief type alleen toewijzen aan een type
alias:
type MilkshakeName = string;interface Milkshake { name: MilkshakeName; price: number;}
Als u een primitief moet gebruiken, gebruik dan een type
. Interfaces zijn een no-go hier voor slechts een enkele waarde, omdat de syntaxis het niet ondersteunt.
🎉 Download het gratis!
Klaar om verder te gaan dan ForEach? Krijg vertrouwen met geavanceerde methoden – Reduce, Find, Filter, Every, Some en Map.
- Begrijp volledig hoe JavaScript Data Structuren te beheren met onveranderlijke operaties
- 31 pagina’s met diepgaande syntaxis, real-world voorbeelden, tips en trucs
- Schrijf schonere en beter gestructureerde programmeer logica binnen 3 uur
Als extra bonus, sturen we u ook nog wat extra goodies via een paar extra e-mails.
In de meeste gevallen is het echter eenvoudiger om de primitieve waarde direct te gebruiken:
interface Milkshake { name: string; price: number;}
Maak je code niet te ingewikkeld!
Klassen: Type vs Interface
Of je nu een type
of interface
hebt gekozen, de manier waarop we het met een klasse gebruiken is hetzelfde:
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 ; }}
Klassen bieden geen ondersteuning voor het implementeren/uitbreiden van union types, omdat ze worden beschouwd als statische blauwdrukken. Dit betekent dat je heel expliciet moet zijn over elk type dat je implementeert, omdat het op dit moment niet dynamisch kan zijn of kan veranderen vanwege de beperkingen van TypeScript.
Lees meer over TypeScript Interfaces vs Classes!
Functies: Type vs Interface
Typisch zou ik een functie maken met behulp van de type
alias, omdat we meestal een anonieme functie willen typen:
type IngredientsFn = () => string;const getIngredients: IngredientsFn = () => ;
Maar als het gebruik van een interface
hiervoor meer jouw stijl zou zijn, dan lees je hier hoe je dat moet doen:
interface IngredientsFn { () => string;}
Het voelt een beetje vreemd in vergelijking met het gebruik van type
, maar nogmaals, beide zijn volledig geldig TypeScript en er is geen verschil wanneer de code wordt gecompileerd.
Wanneer een Type niet gebruiken
Nu we de verschillende vergelijkingen en aanbevolen benaderingen hebben onderzocht, is het tijd om te praten over Declaration Merging, een functie in TypeScript die alleen van toepassing is op interface
en een reden zou zijn om een interface
boven een type
te kiezen.
Om types met type
samen te voegen, zouden we iets als dit moeten doen en een nieuwe finale type
moeten maken:
type MilkshakeProps = { name: string; price: number;};type MilkshakeMethods = { getIngredients(): string;};type Milkshake = MilkshakeProps & MilkshakeMethods;
Onze type Milkshake
is nu een type alias van MilkshakeProps
en MilkshakeMethods
. Merk op, dat om dit gedrag te bereiken we Milkshake
hebben moeten maken, waardoor we 3 individuele type aliassen hebben.
Met interfaces, is er in feite een slimmere aanpak (sommigen zouden kunnen zeggen een beetje te slim) genaamd declaratie samenvoegen.
We kunnen een samenvoeging van declaraties bereiken door eenvoudigweg dezelfde interface
tweemaal in hetzelfde bereik te declareren (dit kan zijn via het importeren van de interface uit een andere module, of door hem lokaal naast een andere interface te declareren):
// 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 bevat nu name
, price
en getIngredients
! Maar is het samenvoegen van verklaringen een goede zaak? Ik ben er eerlijk gezegd geen fan van en ik heb het gevoel dat het meer kwaad dan goed zou kunnen doen. Ik zou je types samenstellen met type
in plaats van declaratie-samenvoeging te gebruiken – maar je weet nu tenminste wat de belangrijkste verschillen zijn.
Conclusie
Daar heb je het! De belangrijkste verschillen tussen Types en Interfaces in TypeScript.
Om samen te vatten, met ook wat persoonlijke voorkeuren, zou ik het houden bij een interface
voor objecten en het type
alias keyword gebruiken om nieuwe types on the fly samen te stellen. Deze nieuwe types kunnen zelfs van interfaces of andere types zijn, zoals tuples, unions en intersection types. Er zijn veel mogelijkheden, maar door de benaderingen te begrijpen kunnen we beginnen met het kiezen van het juiste gereedschap.
Voor het grootste deel zijn interfaces en types vrijwel hetzelfde, afgezien van een paar verschillen die hier zijn behandeld. Ik hoop dat je het leuk vond om te lezen!
Als je TypeScript-vaardigheden serieus wilt nemen, is de volgende stap een kijkje nemen bij mijn TypeScript-cursussen. Daar leer je de basis van de taal in detail, evenals veel geavanceerde use-cases die je nodig hebt bij de dagelijkse TypeScript-ontwikkeling!
Happy coding!