TypeScript – Interfaces

Interface er en struktur, der definerer kontrakten i din applikation. Den definerer den syntaks, som klasser skal følge. Klasser, der er afledt af en grænseflade, skal følge den struktur, som deres grænseflade giver.

TypeScript-kompileren konverterer ikke grænseflade til JavaScript. Den bruger interface til typekontrol. Dette er også kendt som “duck typing” eller “structural subtyping”.

En grænseflade defineres med nøgleordet interface, og den kan indeholde egenskaber og metodeklarationer ved hjælp af en funktion eller en pilefunktion.

Eksempel: Interface

Kopier

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

I ovenstående eksempel omfatter IEmployee-grænsefladen to egenskaber empCode og empName. Den indeholder også en metodeerklæring getSalaray ved hjælp af en pilefunktion, der indeholder en talparameter og en talreturtype. Metoden getManagerName er deklareret ved hjælp af en normal funktion. Det betyder, at ethvert objekt af typen IEmployee skal definere de to egenskaber og de to metoder.

Interface som type

Interface i TypeScript kan bruges til at definere en type og også til at implementere den i klassen.

Den følgende grænseflade IEmployee definerer en type af en variabel.

Eksempel: Interface som type

Kopier

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 ovenstående eksempel indeholder en grænseflade KeyPair to egenskaber key og value. En variabel kv1 er erklæret som KeyPair type. Så den skal følge den samme struktur som KeyPair. Det betyder, at kun et objekt med egenskaberne key af typen tal og value af typen streng kan tildeles en variabel kv1. TypeScript-kompileren vil vise en fejl, hvis der sker en ændring i navnet på egenskaberne, eller hvis datatypen er anderledes end KeyPair. En anden variabel kv2 er også deklareret som KeyPair type, men den tildelte værdi er val i stedet for value, så dette vil medføre en fejl. På samme måde tildeler kv3 et tal til egenskaben value, så compileren vil vise en fejl. TypeScript bruger således en grænseflade til at sikre den korrekte struktur af et objekt.

Interface som funktionstype

TypeScript-interface bruges også til at definere en type for en funktion. Dette sikrer funktionssignaturen.

Eksempel: Funktionstype

Kopier

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 ovenstående eksempel indeholder en grænseflade KeyValueProcessor en metodesignatur. Denne definerer funktionstypen. Nu kan vi definere en variabel af typen KeyValueProcessor, som kun kan pege på funktioner med den samme signatur som defineret i grænsefladen KeyValueProcessor. Så addKeyValue eller updateKeyValue-funktionen tildeles kvp. Så kvp kan kaldes som en funktion.

Vil du forsøge at tildele en funktion med en anden signatur, opstår der en fejl.

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

ADVERTISERING

Interface for Array Type

En interface kan også definere typen af et array, hvor du kan definere typen af indeks samt værdier.

Eksempel: Type af array

Kopier

interface NumList { :number}let numArr: NumList = ;numArr;numArr;interface IStringList { :string}let strArr : IStringList;strArr = "TypeScript";strArr = "JavaScript";

I ovenstående eksempel definerer grænseflade NumList en type af array med indeks som tal og værdi som taltype. På samme måde definerer IStringList et array af strengtype med indeks som streng og værdi som streng.

Optionel egenskab

Nogle gange kan vi deklarere en grænseflade med overskydende egenskaber, men vi forventer måske ikke, at alle objekter definerer alle de givne grænsefladeegenskaber. Vi kan have valgfrie egenskaber, der er markeret med et “?”. I sådanne tilfælde kan objekter i grænsefladen definere disse egenskaber eller ej.

Eksempel: Valgfri egenskab

Kopier

interface IEmployee { empCode: number; empName: string; empDept?:string;}let empObj1:IEmployee = { // OK empCode:1, empName:"Steve"}let empObj2:IEmployee = { // OK empCode:1, empName:"Bill", empDept:"IT"}

I ovenstående eksempel er empDept markeret med ?, så objekter af IEmployee kan eller kan ikke indeholde denne egenskab.

Nej læsebeskyttede egenskaber

TypeScript giver en måde at markere en egenskab som kun læsebeskyttet. Det betyder, at når først en egenskab er tildelt en værdi, kan den ikke ændres!

Eksempel: Readonly Property

Kopier

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 ovenstående eksempel er SSN-egenskaben skrivebeskyttet. Vi definerer objektet personObj af typen Citizen og tildeler værdier til de to grænsefladeegenskaber. Dernæst forsøger vi at ændre de værdier, der er tildelt begge egenskaber-name og SSN. TypeScript-kompileren viser en fejl, når vi forsøger at ændre den skrivebeskyttede SSN-egenskab.

Udvidelse af grænseflader

Interfaces kan udvide en eller flere grænseflader. Dette gør det fleksibelt og genanvendeligt at skrive grænseflader.

Eksempel: Udvid grænseflade

Kopier

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

I ovenstående eksempel udvider IEmployee-grænsefladen IPerson-grænsefladen. Så objekter af IEmployee skal indeholde alle egenskaberne og metoderne i IPerson-grænsefladen, ellers viser compileren en fejl.

Implementering af en grænseflade

Som i sprog som Java og C# kan grænseflader i TypeScript implementeres med en klasse. Klassen, der implementerer grænsefladen, skal strengt overholde strukturen for grænsefladen.

Eksempel: I ovenstående eksempel er grænsefladen IEmployee implementeret i klassen Employee ved hjælp af nøgleordet implement. Den implementerende klasse skal strengt definere egenskaberne og funktionen med samme navn og datatype. Hvis den implementerende klasse ikke følger strukturen, vil compileren vise en fejl.

Den implementerende klasse kan selvfølgelig definere ekstra egenskaber og metoder, men den skal i det mindste definere alle medlemmerne af en grænseflade.

I næste kapitel lærer vi mere om TypeScript-klasser.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.