TypeScript – gränssnitt

Interface är en struktur som definierar kontraktet i ditt program. Det definierar syntaxen för klasser att följa. Klasser som är härledda från ett gränssnitt måste följa den struktur som tillhandahålls av deras gränssnitt.

TypeScript-kompilatorn konverterar inte gränssnitt till JavaScript. Den använder gränssnittet för typkontroll. Detta kallas även ”duck typing” eller ”structural subtyping”.

Ett gränssnitt definieras med nyckelordet interface och kan innehålla egenskaper och metoddeklarationer med hjälp av en funktion eller en pilfunktion.

Exempel: Gränssnitt

Kopiera

interface IEmployee { empCode: number; empName: string; getSalary: (number) => number; // arrow function getManagerName(number): string; }

I exemplet ovan innehåller gränssnittet IEmployee två egenskaper empCode och empName. Det innehåller också en metoddeklaration getSalaray som använder en pilfunktion som innehåller en sifferparameter och en sifferreturtyp. Metoden getManagerName deklareras med en normal funktion. Detta innebär att varje objekt av typen IEmployee måste definiera de två egenskaperna och de två metoderna.

Interface som typ

Interface i TypeScript kan användas för att definiera en typ och även för att implementera den i klassen.

Följande interface IEmployee definierar en typ av en variabel.

Exempel: Gränssnitt som typ

Kopiera

interface KeyPair { key: number; value: string;}let kv1: KeyPair = { key:1, value:"Steve" }; // OKlet kv2: KeyPair = { key:1, val:"Steve" }; // Compiler Error: 'val' doesn't exist in type 'KeyPair'let kv3: KeyPair = { key:1, value:100 }; // Compiler Error: 

I exemplet ovan innehåller ett gränssnitt KeyPair två egenskaper key och value. En variabel kv1 deklareras som KeyPair typ. Den måste alltså följa samma struktur som KeyPair. Det innebär att endast ett objekt med egenskaperna key av taltyp och value av strängtyp kan tilldelas en variabel kv1. TypeScript-kompilatorn visar ett fel om namnet på egenskaperna ändras eller om datatypen skiljer sig från KeyPair. En annan variabel kv2 är också deklarerad som KeyPair typ men det tilldelade värdet är val istället för value, så detta kommer att orsaka ett fel. På samma sätt tilldelar kv3 ett nummer till egenskapen value, så kompilatorn kommer att visa ett fel. TypeScript använder alltså ett gränssnitt för att säkerställa att ett objekt har rätt struktur.

Interface som funktionstyp

TypeScript-gränssnitt används också för att definiera en funktionstyp. Detta säkerställer funktionssignaturen.

Exempel: Funktionstyp

Kopiera

interface KeyValueProcessor{ (key: number, value: string): void;};function addKeyValue(key:number, value:string):void { console.log('addKeyValue: key = ' + key + ', value = ' + value)}function updateKeyValue(key: number, value:string):void { console.log('updateKeyValue: key = '+ key + ', value = ' + value)} let kvp: KeyValueProcessor = addKeyValue;kvp(1, 'Bill'); //Output: addKeyValue: key = 1, value = Bill kvp = updateKeyValue;kvp(2, 'Steve'); //Output: updateKeyValue: key = 2, value = Steve 

I ovanstående exempel innehåller ett gränssnitt KeyValueProcessor en metodsignatur. Denna definierar funktionstypen. Nu kan vi definiera en variabel av typen KeyValueProcessor som endast kan peka på funktioner med samma signatur som definieras i gränssnittet KeyValueProcessor. Så addKeyValue eller updateKeyValue funktion tilldelas kvp. Så kvp kan anropas som en funktion.

Vetar du att tilldela en funktion med en annan signatur uppstår ett fel.

function delete(key:number):void { console.log('Key deleted.')} let kvp: KeyValueProcessor = delete; //Compiler Error

ADVERTISERING

Interface för array-typ

Ett gränssnitt kan också definiera typen av en array där du kan definiera typen av index såväl som värden.

Exempel: I exemplet ovan definierar gränssnittet NumList en typ av array med index som nummer och värde som nummertyp. På samma sätt definierar IStringList en strängarray med index som sträng och värde som sträng.

Optionell egenskap

Ibland kan vi deklarera ett gränssnitt med överflödiga egenskaper men kanske inte förväntar oss att alla objekt ska definiera alla givna gränssnittsegenskaper. Vi kan ha valfria egenskaper, markerade med ett ”?”. I sådana fall kan objekt i gränssnittet definiera dessa egenskaper eller inte.

Exempel: I exemplet ovan är empDept markerad med ?, så objekt av IEmployee kan inkludera den här egenskapen eller inte.

Enbart läsbara egenskaper

TypeScript erbjuder ett sätt att markera en egenskap som endast läsbar. Detta innebär att när en egenskap har tilldelats ett värde kan den inte ändras!

Exempel: Exemplet: Egenskap som är skrivskyddad

Kopiera

interface Citizen { name: string; readonly SSN: number;}let personObj: Citizen = { SSN: 110555444, name: 'James Bond' }personObj.name = 'Steve Smith'; // OKpersonObj.SSN = '333666888'; // Compiler Error

I exemplet ovan är egenskapen SSN skrivskyddad. Vi definierar objektet personObj av typen Citizen och tilldelar värden till de två gränssnittsegenskaperna. Därefter försöker vi ändra de värden som tilldelats de båda egenskaperna name och SSN. TypeScript-kompilatorn visar ett fel när vi försöker ändra den skrivskyddade egenskapen SSN.

Utvidgning av gränssnitt

Gränssnitt kan utvidga ett eller flera gränssnitt. Detta gör det flexibelt och återanvändbart att skriva gränssnitt.

Exempel: Utöka gränssnitt

Kopiera

interface IPerson { name: string; gender: string;}interface IEmployee extends IPerson { empCode: number;}let empObj:IEmployee = { empCode:1, name:"Bill", gender:"Male"}

I ovanstående exempel utökar gränssnittet IEmployee gränssnittet IPerson gränssnittet IPerson. Så objekt av IEmployee måste innehålla alla egenskaper och metoder i IPerson-gränssnittet, annars visar kompilatorn ett fel.

Implementering av ett gränssnitt

I likhet med språk som Java och C# kan gränssnitt i TypeScript implementeras med en Class. Klassen som implementerar gränssnittet måste strikt följa gränssnittets struktur.

Exempel: I exemplet ovan implementeras gränssnittet IEmployee i klassen Employee med hjälp av nyckelordet implement. Den implementerande klassen bör strikt definiera egenskaperna och funktionen med samma namn och datatyp. Om den implementerande klassen inte följer strukturen kommer kompilatorn att visa ett fel.

Självklart kan den implementerande klassen definiera extra egenskaper och metoder, men den måste åtminstone definiera alla medlemmar i ett gränssnitt.

I nästa kapitel kommer vi att lära oss mer om TypeScript-klasser.

Lämna ett svar

Din e-postadress kommer inte publiceras.