Az interfész egy olyan struktúra, amely meghatározza a szerződést az alkalmazásban. Meghatározza az osztályok számára követendő szintaxist. Az interfészből származtatott osztályoknak követniük kell az interfészük által megadott struktúrát.
A TypeScript fordító nem konvertálja az interfészeket JavaScriptre. A típusellenőrzéshez interfészt használ. Ezt “kacsatipizálásnak” vagy “strukturális altipizálásnak” is nevezik.
Az interfész a interface
kulcsszóval definiálható, és tartalmazhat tulajdonságokat és metódusdeklarációkat függvény vagy nyílfüggvény segítségével.
IEmployee
interfész két tulajdonságot empCode
és empName
tartalmaz: Másolás
interface IEmployee { empCode: number; empName: string; getSalary: (number) => number; // arrow function getManagerName(number): string; }
. Tartalmaz továbbá egy getSalaray
metódusdeklarációt is, amely egy nyílfüggvényt használ, amely egy szám paramétert és egy szám visszatérési típust tartalmaz. A getManagerName
metódus egy normál függvény használatával van deklarálva. Ez azt jelenti, hogy bármely IEmployee
típusú objektumnak meg kell határoznia a két tulajdonságot és a két metódust.
Interfész mint típus
A TypeScriptben az interfész használható egy típus definiálására és az osztályban való implementálására is.
A következő IEmployee
interfész egy változó típusát definiálja.
Copy
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:
A fenti példában egy KeyPair
interfész két tulajdonságot tartalmaz key
és value
. A kv1
változót KeyPair
típusúnak deklaráljuk. Tehát ugyanazt a struktúrát kell követnie, mint a KeyPair
. Ez azt jelenti, hogy egy kv1
változóhoz csak egy key
szám típusú és value
karakterlánc típusú tulajdonságokkal rendelkező objektumot lehet hozzárendelni. A TypeScript fordító hibát fog mutatni, ha a tulajdonságok neve megváltozik, vagy az adattípus eltér a KeyPair
-tól. Egy másik változó kv2
szintén KeyPair
típusúnak van deklarálva, de a hozzárendelt érték value
helyett val
, így ez hibát fog okozni. Ugyanígy a kv3 a value
tulajdonsághoz egy számot rendel, így a fordító hibát fog mutatni. A TypeScript tehát egy interfész segítségével biztosítja az objektum megfelelő felépítését.
Interfész mint függvénytípus
A TypeScript interfész is használható egy függvény típusának meghatározására. Ez biztosítja a függvény szignatúráját.
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
A fenti példában egy KeyValueProcessor
interfész tartalmaz egy metódus aláírását. Ez határozza meg a függvénytípust. Most definiálhatunk egy KeyValueProcessor
típusú változót, amely csak a KeyValueProcessor
interfészben definiált aláírással rendelkező függvényekre mutathat. Tehát a addKeyValue
vagy updateKeyValue
függvényt a kvp
függvényhez rendeljük. Így a kvp
függvényként hívható.
Az eltérő aláírású függvény hozzárendelésének kísérlete hibát okoz.
function delete(key:number):void { console.log('Key deleted.')} let kvp: KeyValueProcessor = delete; //Compiler Error
Interface for Array Type
Egy interfész is meghatározhatja egy tömb típusát, ahol az index és az értékek típusa is meghatározható.
Másolás
interface NumList { :number}let numArr: NumList = ;numArr;numArr;interface IStringList { :string}let strArr : IStringList;strArr = "TypeScript";strArr = "JavaScript";
A fenti példában a NumList
interfész definiál egy olyan típusú tömböt, amelynek indexe szám, értéke pedig szám típusú. Ugyanígy a IStringList
egy string tömböt definiál, amelynek indexe string, értéke pedig string.
Optionális tulajdonság
Néha előfordulhat, hogy egy interfészt többlet tulajdonságokkal deklarálunk, de nem várjuk el, hogy minden objektum definiálja az összes megadott interfész tulajdonságot. Lehetnek opcionális tulajdonságaink, amelyeket “?”-val jelölünk. Ilyen esetekben az interfész objektumai definiálhatják vagy nem definiálhatják ezeket a tulajdonságokat.
Másolás
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"}
A fenti példában a empDept
a ?
jelöléssel van ellátva, így a IEmployee
objektumai tartalmazhatják vagy nem tartalmazhatják ezt a tulajdonságot.
Csak olvasható tulajdonságok
A TypeScript lehetőséget biztosít egy tulajdonság csak olvashatónak jelölésére. Ez azt jelenti, hogy ha egy tulajdonságnak egyszer értéket adunk, akkor az nem változtatható meg!
interface Citizen { name: string; readonly SSN: number;}let personObj: Citizen = { SSN: 110555444, name: 'James Bond' }personObj.name = 'Steve Smith'; // OKpersonObj.SSN = '333666888'; // Compiler Error
A fenti példában a SSN
tulajdonság csak olvasható. Meghatározzuk a personObj objektumot Citizen típusúnak, és értékeket rendelünk a két interfész-tulajdonsághoz. Ezután megpróbáljuk megváltoztatni a két tulajdonsághoz – name
és SSN
– hozzárendelt értékeket. A TypeScript fordító hibát mutat, amikor megpróbáljuk megváltoztatni a csak olvasható SSN
tulajdonságot.
Az interfészek kiterjesztése
Az interfészek egy vagy több interfészt is kiterjeszthetnek. Ez rugalmassá és újrafelhasználhatóvá teszi az interfészek írását.
Copy
interface IPerson { name: string; gender: string;}interface IEmployee extends IPerson { empCode: number;}let empObj:IEmployee = { empCode:1, name:"Bill", gender:"Male"}
A fenti példában a IEmployee
interfész kiterjeszti a IPerson
interfészt. Tehát a IEmployee
objektumainak tartalmazniuk kell a IPerson
interfész összes tulajdonságát és metódusát, különben a fordító hibát fog mutatni.
Interfész megvalósítása
A TypeScriptben az olyan nyelvekhez hasonlóan, mint a Java és a C#, az interfészeket egy osztállyal lehet megvalósítani. Az interfészt megvalósító osztálynak szigorúan meg kell felelnie az interfész szerkezetének.
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");
A fenti példában a IEmployee
interfészt az Employee osztályban implementáljuk az implement kulcsszóval. Az implementáló osztálynak szigorúan azonos névvel és adattípussal kell definiálnia a tulajdonságokat és a függvényt. Ha az implementáló osztály nem követi a struktúrát, akkor a fordító hibát fog mutatni.
A megvalósító osztály természetesen definiálhat extra tulajdonságokat és metódusokat, de legalábbis egy interfész összes tagját definiálnia kell.
A következő fejezetben többet fogunk megtudni a TypeScript osztályokról.