TypeScript för nybörjare, del 3 gränssnitt

Vi började den här serien med en introduktionstutorial som introducerade dig till olika TypeScript-funktioner. Det lärde dig också hur du installerar TypeScript och föreslog några IDE som du kan använda för att skriva och sammanställa din egen TypeScript-kod. 

I den andra handledningen täckte vi olika datatyper som finns tillgängliga i TypeScript och hur du använder dem kan hjälpa dig att undvika många fel. Tilldela en datatyp som a sträng till en viss variabel berättar TypeScript att du bara vill tilldela en sträng till den. Med hjälp av denna information kan TypeScript peka ut det senare till dig när du försöker utföra en operation som inte ska utföras på strängar.

I denna handledning lär du dig information om gränssnitt i TypeScript. Med gränssnitt kan du gå ett steg längre och definiera strukturen eller typen av mer komplexa objekt i din kod. Precis som enkla variabla typer måste dessa objekt också följa en uppsättning regler skapade av dig. Detta kan hjälpa dig att skriva kod mer konfidentiellt, med mindre chans att få fel.

Skapa vårt första gränssnitt

Låt oss säga att du har ett sjöobjekt i din kod, och du använder den för att lagra information om några av de största sjöarna efter område runt om i världen. Detta sjöobjekt kommer att ha egenskaper som sjöns namn, dess yta, längd, djup och de länder där den där sjön finns.

Namnen på sjöarna kommer att lagras som en sträng. Längden av dessa sjöar kommer att ligga i kilometer, och områdena kommer att ligga i kvadratkilometer, men båda dessa egenskaper lagras som nummer. Djuparna av sjöarna kommer att vara i meter, och detta kan också vara en flottör. 

Eftersom alla dessa sjöar är mycket stora är deras strandlinjer i allmänhet inte begränsade till ett enda land. Vi kommer att använda en rad strängar för att lagra namnen på alla länder på kusten av en viss sjö. En booleska kan användas för att specificera om sjön är saltvatten eller färskvatten. Följande kodfragment skapar ett gränssnitt för vårt sjöobjekt.

gränssnitt sjöar namn: sträng, område: nummer, längd: antal, djup: nummer, isFreshwater: booleska, länder: sträng []

De Lakes gränssnittet innehåller typen av varje egendom som vi ska använda när vi skapar våra sjöobjekt. Om du försöker att tilldela olika typer av värden till någon av dessa egenskaper får du ett fel. Här är ett exempel som lagrar information om vår första sjö.

låt firstLake: Lakes = namn: 'Caspian Sea', längd: 1199, djup: 1025, areal: 371000, isFreshwater: falskt, länder: ['Kazakstan', 'Ryssland', 'Turkmenistan', 'Azerbajdzjan', 'Iran ']

Som du kan se, spelar den ordning i vilken du tilldelar ett värde till dessa egenskaper ingen roll. Du kan dock inte utelämna ett värde. Du måste ange ett värde för varje egendom för att undvika fel när du sammanställer koden. 

På detta sätt säkerställer TypeScript att du inte missade några av de nödvändiga värdena av misstag. Här är ett exempel där vi glömde att tilldela värdet av djup egendom för en sjö.

låt secondLake: Lakes = namn: 'Superior', längd: 616, area: 82100, isFreshwater: true, countries: ['Kanada', 'United States']

Skärmbilden nedan visar felmeddelandet i Visual Studio Code efter att vi glömde att ange djup. Som du kan se, påpekar felet tydligt att vi saknar djup egendom för vårt sjöobjekt.

Göra gränssnittsegenskaper Valfritt

Ibland behöver du bara en egenskap för vissa specifika objekt. Låt oss till exempel säga att du vill lägga till en egendom för att ange de månader då en sjö är frusen. Om du lägger till fastigheten direkt till gränssnittet, som vi har gjort tills nu, kommer du att få ett fel för andra sjöar som inte fryser och därför inte har någon frysta fast egendom. På samma sätt, om du lägger till den här egenskapen till sjöar som är frysta men inte i gränssnittsdeklarationen, kommer du fortfarande att få ett fel.

I sådana fall kan du lägga till ett frågetecken (?) efter namnet på en egenskap för att ställa in den som valfri i gränssnittsdeklarationen. På så sätt får du inte ett fel för saknade egenskaper eller okända egenskaper. Följande exempel ska göra det klart.

gränssnitt sjöar namn: sträng, område: nummer, längd: antal, djup: nummer, isFreshwater: booleska, länder: sträng [], frusen ?: sträng [] låt secondLake: Lakes = name: 'Superior' 406.3, längd: 616, areal: 82100, isFreshwater: true, countries: ['Kanada', 'United States'] Låt tredjeLake: Lakes = namn: 'Baikal', djup: 1637, längd: 636, område: 31500 , isFreshwater: true, countries: ['Russia'], fryst: ['januari', 'februari', 'mars', 'april', 'maj']

Använda Index Signatures

Valfria egenskaper är användbara när en del av dina objekt ska använda dem. Men, om varje sjö också hade sin egen unika uppsättning egenskaper som ekonomisk verksamhet, blommar befolkningen i olika slags flora och fauna i den där sjön eller bosättningarna runt sjön? Att lägga så många olika egenskaper inuti deklarationen av gränssnittet själv och göra dem valfria är inte idealisk.

Som en lösning kan du med TypScript lägga till extra egenskaper till specifika objekt med hjälp av index signaturer. Om du lägger till en index signatur i gränssnittsdeklarationen kan du ange ett antal egenskaper för olika objekt som du skapar. Du måste göra följande ändringar i gränssnittet. 

I det här exemplet har jag använt indexindex för att lägga till information om olika bosättningar runt sjöarna. Eftersom varje sjö kommer att ha sina egna bosättningar, skulle det inte ha varit en bra idé med valfria egenskaper.

gränssnitt sjöar namn: sträng, område: nummer, längd: antal, djup: nummer, isFreshwater: booleska, länder: sträng [], frusen ?: sträng [], [extraProp: sträng]: någon släpp fourthLake: Lakes =  Namn: 'Tanganyika', djup: 1470, längd: 676, areal: 32600, isFreshwater: true, countries: ['Burundi', 'Tanzania', 'Zambia', 'Kongo'], kigoma: 'Tanzania', kalemie: "Kongo", bujumbura: "Burundi"

Som ett annat exempel, låt oss säga att du skapar ett spel med olika typer av fiender. Alla dessa fiender kommer att ha några gemensamma egenskaper som deras storlek och hälsa. Dessa egenskaper kan direkt ingå i gränssnittsdeklarationen. Om varje kategori av dessa fiender har en unik uppsättning vapen, kan dessa vapen inkluderas med hjälp av en index signatur.

Endast skrivskyddade egenskaper

När du arbetar med olika objekt kan du behöva arbeta med egenskaper som bara ska ändras när vi först skapar objektet. Du kan markera dessa egenskaper som readonly i gränssnittsdeklarationen. Detta liknar att använda const sökord, men const är tänkt att användas med variabler, medan readonly är avsedd för egenskaper.

TypeScript låter dig också göra arrays skrivskyddade med hjälp av ReadonlyArray. Att skapa en skrivskyddad matris resulterar i att alla mutationsmetoder tas bort från den. Detta görs för att du inte kan ändra värdet av enskilda element senare. Här är ett exempel på att använda skrivskyddade egenskaper och arrayer i gränssnittsdeklarationer.

gränssnitt Enemy readonly storlek: nummer, hälsa: antal, intervall: antal, skadade skador: nummer låt tanken: Enemy = storlek: 50, hälsa: 100, intervall: 60, skada: 12 // Detta är okej tank. hälsa = 95; // Fel eftersom "skada" är skrivskyddad. tank.damage = 10;

Funktioner och gränssnitt

Du kan också använda gränssnitt för att beskriva en funktionstyp. Detta kräver att du ger funktionen en samtalssignatur med parametervärden och returtyp. Du måste också ange både ett namn och en typ för var och en av parametrarna. Här är ett exempel:

gränssnitt EnemyHit (namn: Enemy, damageDone: number): number;  låt tankHit: EnemyHit = funktion (tankName: Enemy, damageDone: number) tankName.health - = damageDone; returtanknamn.health; 

I ovanstående kod har vi förklarat ett funktionsgränssnitt och använt det för att definiera en funktion som subtraherar den skada som behandlas på en tank från sin hälsa. Som du kan se behöver du inte använda samma namn för parametrar i gränssnittsdeklarationen och definitionen för koden att fungera.

Slutgiltiga tankar

Denna handledning introducerade dig till gränssnitt och hur du kan använda dem för att se till att du skriver mer robust kod. Du borde nu kunna skapa egna gränssnitt med frivilliga och skrivskyddade egenskaper. 

Du lärde dig också att använda indexsignaturer för att lägga till en rad andra egenskaper till ett objekt som inte ingår i gränssnittsdeklarationen. Denna handledning var tänkt att komma igång med gränssnitt i TypeScript, och du kan läsa mer om detta ämne i den officiella dokumentationen.

I nästa handledning lär du dig information om klasser i TypeScript. Om du har några frågor relaterade till gränssnitt, låt mig veta i kommentarerna.