Interface is een structuur die het contract in uw applicatie definieert. Het definieert de syntax voor klassen om te volgen. Klassen die van een interface zijn afgeleid, moeten de structuur van hun interface volgen.
De TypeScript-compiler zet geen interface om in JavaScript. Hij gebruikt de interface voor typecontrole. Dit staat ook bekend als “duck typing” of “structural subtyping”.
Een interface wordt gedefinieerd met het trefwoord interface
en het kan eigenschappen en methodeverklaringen bevatten met behulp van een functie of een pijlfunctie.
Copy
interface IEmployee { empCode: number; empName: string; getSalary: (number) => number; // arrow function getManagerName(number): string; }
In het bovenstaande voorbeeld bevat de interface IEmployee
twee eigenschappen empCode
en empName
. Het bevat ook een methode-declaratie getSalaray
die gebruik maakt van een pijlfunctie die een parameter voor een getal en een terugkeertype voor een getal bevat. De methode getManagerName
wordt gedeclareerd met een normale functie. Dit betekent dat elk object van het type IEmployee
de twee eigenschappen en de twee methoden moet definiëren.
Interface als Type
Interface in TypeScript kan worden gebruikt om een type te definiëren en ook om het te implementeren in de klasse.
De volgende interface IEmployee
definieert een type van een variabele.
Kopiëren
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:
In het bovenstaande voorbeeld bevat een interface KeyPair
twee eigenschappen key
en value
. Een variabele kv1
wordt gedeclareerd als KeyPair
type. Zij moet dus dezelfde structuur hebben als KeyPair
. Dit betekent dat alleen een object met eigenschappen key
van het type getallen en value
van het type tekenreeks kan worden toegewezen aan een variabele kv1
. De TypeScript compiler zal een fout laten zien als de naam van de eigenschappen verandert of als het data type anders is dan KeyPair
. Een andere variabele kv2
is ook gedeclareerd als KeyPair
type maar de toegekende waarde is val
in plaats van value
, dus dit zal een fout opleveren. Op dezelfde manier wijst kv3 een getal toe aan de value
eigenschap, dus de compiler zal een fout laten zien. TypeScript gebruikt dus een interface om de juiste structuur van een object te verzekeren.
Interface als Functietype
TypeScript interface wordt ook gebruikt om een type van een functie te definiëren. Dit zorgt voor de functiehandtekening.
Copy
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
In bovenstaand voorbeeld bevat een interface KeyValueProcessor
een methode handtekening. Deze definieert het functietype. Nu kunnen we een variabele van het type KeyValueProcessor
definiëren die alleen kan wijzen naar functies met dezelfde signatuur als gedefinieerd in de interface KeyValueProcessor
. Dus, addKeyValue
of updateKeyValue
functie wordt toegewezen aan kvp
. Dus, kvp
kan worden aangeroepen als een functie.
Probeert u een functie met een andere signatuur toe te wijzen, dan geeft dat een fout.
function delete(key:number):void { console.log('Key deleted.')} let kvp: KeyValueProcessor = delete; //Compiler Error
Interface voor Array Type
Een interface kan ook het type van een array definiëren, waarbij u zowel het type van de index als van de waarden kunt definiëren.
Copy
interface NumList { :number}let numArr: NumList = ;numArr;numArr;interface IStringList { :string}let strArr : IStringList;strArr = "TypeScript";strArr = "JavaScript";
In het bovenstaande voorbeeld definieert interface NumList
een type array met index als getal en waarde als getallentype. Op dezelfde manier definieert IStringList
een string-array met index als string en waarde als string.
Optional Property
Soms kunnen we een interface declareren met een overmaat aan eigenschappen, maar verwachten we niet dat alle objecten alle gegeven interface-eigenschappen zullen definiëren. We kunnen optionele eigenschappen hebben, gemarkeerd met een “?”. In dergelijke gevallen kunnen objecten van de interface deze eigenschappen al dan niet definiëren.
Copy
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"}
In bovenstaand voorbeeld is empDept
gemarkeerd met ?
, dus objecten van IEmployee
kunnen deze eigenschap wel of niet bevatten.
Read only Properties
TypeScript voorziet in een manier om een eigenschap als read only te markeren. Dit betekent dat wanneer aan een eigenschap eenmaal een waarde is toegekend, deze niet meer kan worden gewijzigd!
Copy
interface Citizen { name: string; readonly SSN: number;}let personObj: Citizen = { SSN: 110555444, name: 'James Bond' }personObj.name = 'Steve Smith'; // OKpersonObj.SSN = '333666888'; // Compiler Error
In het bovenstaande voorbeeld is de SSN
eigenschap alleen-lezen. Wij definiëren het object personObj van het type Burger en kennen waarden toe aan de twee interface-eigenschappen. Vervolgens proberen wij de waarden van beide eigenschappen –name
en SSN
– te veranderen. De TypeScript compiler zal een fout laten zien wanneer we proberen de alleen-lezen SSN
eigenschap te veranderen.
Extending Interfaces
Interfaces kunnen een of meer interfaces uitbreiden. Dit maakt het schrijven van interfaces flexibel en herbruikbaar.
Copy
interface IPerson { name: string; gender: string;}interface IEmployee extends IPerson { empCode: number;}let empObj:IEmployee = { empCode:1, name:"Bill", gender:"Male"}
In het bovenstaande voorbeeld breidt de IEmployee
interface de IPerson
interface uit. Dus, objecten van IEmployee
moeten alle eigenschappen en methoden van de IPerson
interface bevatten, anders zal de compiler een fout weergeven.
Implementeren van een Interface
Gelijk aan talen als Java en C#, kunnen interfaces in TypeScript worden geïmplementeerd met een Class. De Class die de interface implementeert, moet zich strikt aan de structuur van de interface houden.
Copy
interface IEmployee { empCode: number; name: string; getSalary:(number)=>number;}class Employee implements IEmployee { empCode: number; name: string; constructor(code: number, name: string) { this.empCode = code; this.name = name; } getSalary(empCode:number):number { return 20000; }}let emp = new Employee(1, "Steve");
In het bovenstaande voorbeeld wordt de IEmployee
interface geïmplementeerd in de klasse Employee met behulp van het implement keyword. De implementerende klasse moet strikt de eigenschappen en de functie met dezelfde naam en hetzelfde gegevenstype definiëren. Als de implementerende klasse de structuur niet volgt, dan zal de compiler een fout weergeven.
De implementerende klasse kan natuurlijk extra eigenschappen en methoden definiëren, maar in ieder geval moet zij alle leden van een interface definiëren.
In het volgende hoofdstuk zullen we meer leren over TypeScript-klassen.