Interfața este o structură care definește contractul în aplicația dumneavoastră. Ea definește sintaxa pe care trebuie să o urmeze clasele. Clasele care sunt derivate dintr-o interfață trebuie să urmeze structura furnizată de interfața lor.
Compilatorul TypeScript nu convertește interfața în JavaScript. Folosește interfața pentru verificarea tipului. Acest lucru este cunoscut și sub numele de „duck typing” sau „structural subtyping”.
O interfață este definită cu cuvântul cheie interface
și poate include proprietăți și declarații de metode folosind o funcție sau o funcție săgeată.
Copy
interface IEmployee { empCode: number; empName: string; getSalary: (number) => number; // arrow function getManagerName(number): string; }
În exemplul de mai sus, interfața IEmployee
include două proprietăți empCode
și empName
. Aceasta include, de asemenea, o declarație de metodă getSalaray
care utilizează o funcție săgeată care include un parametru număr și un tip de returnare număr. Metoda getManagerName
este declarată folosind o funcție normală. Aceasta înseamnă că orice obiect de tip IEmployee
trebuie să definească cele două proprietăți și cele două metode.
Interfața ca tip
Interfața în TypeScript poate fi utilizată pentru a defini un tip și, de asemenea, pentru a-l implementa în clasă.
Următoarea interfață IEmployee
definește un tip de variabilă.
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:
În exemplul de mai sus, o interfață KeyPair
include două proprietăți key
și value
. O variabilă kv1
este declarată ca fiind de tipul KeyPair
. Prin urmare, ea trebuie să urmeze aceeași structură ca și KeyPair
. Aceasta înseamnă că numai un obiect cu proprietățile key
de tip număr și value
de tip șir de caractere poate fi atribuit unei variabile kv1
. Compilatorul TypeScript va afișa o eroare în cazul în care există vreo schimbare în numele proprietăților sau tipul de date este diferit de KeyPair
. O altă variabilă kv2
este, de asemenea, declarată ca fiind de tip KeyPair
, dar valoarea atribuită este val
în loc de value
, deci acest lucru va cauza o eroare. În același mod, kv3 atribuie un număr proprietății value
, astfel încât compilatorul va afișa o eroare. Astfel, TypeScript utilizează o interfață pentru a asigura structura corectă a unui obiect.
Interfața ca tip de funcție
Interfața TypeScript este, de asemenea, utilizată pentru a defini un tip de funcție. Astfel se asigură semnătura funcției.
Copie
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
În exemplul de mai sus, o interfață KeyValueProcessor
include o semnătură de metodă. Aceasta definește tipul de funcție. Acum, putem defini o variabilă de tip KeyValueProcessor
care poate indica numai funcții cu aceeași semnătură ca cea definită în interfața KeyValueProcessor
. Astfel, funcția addKeyValue
sau updateKeyValue
este atribuită la kvp
. Astfel, kvp
poate fi apelată ca o funcție.
Încercarea de a atribui o funcție cu o semnătură diferită va cauza o eroare.
function delete(key:number):void { console.log('Key deleted.')} let kvp: KeyValueProcessor = delete; //Compiler Error
Interfață pentru tipul de array
O interfață poate defini, de asemenea, tipul unui array în care se poate defini tipul de index, precum și valorile.
Copie
interface NumList { :number}let numArr: NumList = ;numArr;numArr;interface IStringList { :string}let strArr : IStringList;strArr = "TypeScript";strArr = "JavaScript";
În exemplul de mai sus, interfața NumList
definește un tip de tablou cu indexul ca număr și valoarea ca tip de număr. În același mod, IStringList
definește un array de tip șir de caractere cu indexul ca șir de caractere și valoarea ca șir de caractere.
Proprietate opțională
Uneori, putem declara o interfață cu un exces de proprietăți, dar este posibil să nu ne așteptăm ca toate obiectele să definească toate proprietățile date ale interfeței. Putem avea proprietăți opționale, marcate cu un „?”. În astfel de cazuri, obiectele interfeței pot defini sau nu aceste proprietăți.
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"}
În exemplul de mai sus, empDept
este marcat cu ?
, astfel încât obiectele din IEmployee
pot sau nu să includă această proprietate.
Read only Properties
TypeScript oferă o modalitate de a marca o proprietate ca fiind numai de citire. Acest lucru înseamnă că odată ce unei proprietăți i se atribuie o valoare, aceasta nu mai poate fi modificată!
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
În exemplul de mai sus, proprietatea SSN
este de numai citire. Se definește obiectul personObj de tip Citizen și se atribuie valori celor două proprietăți de interfață. În continuare, încercăm să modificăm valorile atribuite celor două proprietăți – name
și SSN
. Compilatorul TypeScript va afișa o eroare atunci când încercăm să modificăm proprietatea SSN
, care este doar pentru citire.
Extinderea interfețelor
Interfețele pot extinde una sau mai multe interfețe. Acest lucru face ca scrierea interfețelor să fie flexibilă și reutilizabilă.
Copiere
interface IPerson { name: string; gender: string;}interface IEmployee extends IPerson { empCode: number;}let empObj:IEmployee = { empCode:1, name:"Bill", gender:"Male"}
În exemplul de mai sus, interfața IEmployee
extinde interfața IPerson
. Astfel, obiectele din IEmployee
trebuie să includă toate proprietățile și metodele interfeței IPerson
, în caz contrar, compilatorul va afișa o eroare.
Implementarea unei interfețe
Similar cu limbaje precum Java și C#, interfețele din TypeScript pot fi implementate cu o clasă. Clasa care implementează interfața trebuie să se conformeze strict structurii interfeței.
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");
În exemplul de mai sus, interfața IEmployee
este implementată în clasa Employee cu ajutorul cuvântului cheie implement. Clasa care implementează trebuie să definească strict proprietățile și funcția cu același nume și tip de date. În cazul în care clasa de implementare nu respectă structura, atunci compilatorul va afișa o eroare.
Desigur, clasa de implementare poate defini proprietăți și metode suplimentare, dar cel puțin trebuie să definească toți membrii unei interfețe.
În capitolul următor, vom învăța mai multe despre clasele TypeScript.
.