TypeScript – Interfejsy

Interfejs jest strukturą, która definiuje kontrakt w twojej aplikacji. Definiuje składnię, której muszą przestrzegać klasy. Klasy, które wywodzą się z interfejsu muszą przestrzegać struktury dostarczonej przez ich interfejs.

Kompilator TypeScript nie konwertuje interfejsu na JavaScript. Używa on interfejsu do sprawdzania typu. Jest to również znane jako „duck typing” lub „structural subtyping”.

Interfejs jest zdefiniowany za pomocą słowa kluczowego interface i może zawierać właściwości i deklaracje metod za pomocą funkcji lub funkcji strzałki.

Przykład: Interface

Copy

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

W powyższym przykładzie interfejs IEmployee zawiera dwie właściwości empCode i empName. Zawiera on również deklarację metody getSalaray wykorzystującej funkcję strzałki, która zawiera jeden parametr liczbowy i typ zwracany liczbowy. Metoda getManagerName jest zadeklarowana przy użyciu normalnej funkcji. Oznacza to, że każdy obiekt typu IEmployee musi zdefiniować te dwie właściwości i dwie metody.

Interfejs jako typ

Interfejs w TypeScript może być użyty do zdefiniowania typu, a także do zaimplementowania go w klasie.

Następujący interfejs IEmployee definiuje typ zmiennej.

Przykład: Interface as Type

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: 

W powyższym przykładzie interfejs KeyPair zawiera dwie właściwości key i value. Zmienna kv1 jest zadeklarowana jako typ KeyPair. Zatem musi ona mieć taką samą strukturę jak KeyPair. Oznacza to, że do zmiennej kv1 może być przypisany tylko obiekt o właściwościach key typu liczbowego i value typu łańcuchowego. Kompilator TypeScript wyświetli błąd, jeżeli dojdzie do zmiany nazwy właściwości lub typ danych będzie inny niż KeyPair. Inna zmienna kv2 jest również zadeklarowana jako typ KeyPair, ale przypisana wartość to val zamiast value, więc spowoduje to błąd. W ten sam sposób, kv3 przypisuje liczbę do właściwości value, więc kompilator pokaże błąd. Tak więc TypeScript używa interfejsu, aby zapewnić właściwą strukturę obiektu.

Interfejs jako typ funkcji

Interfejs TypeScript jest również używany do definiowania typu funkcji. Zapewnia to sygnaturę funkcji.

Przykład: Typ funkcji

Kopia

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 

W powyższym przykładzie interfejs KeyValueProcessor zawiera sygnaturę metody. To definiuje typ funkcji. Teraz możemy zdefiniować zmienną typu KeyValueProcessor, która może wskazywać tylko na funkcje z taką samą sygnaturą, jak zdefiniowana w interfejsie KeyValueProcessor. Tak więc, addKeyValue lub updateKeyValue funkcja jest przypisana do kvp. Tak więc, kvp może być wywoływany jak funkcja.

Próba przypisania funkcji o innym podpisie spowoduje błąd.

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

ADWERSJA

Interfejs dla typu tablicy

Interfejs może również definiować typ tablicy, gdzie można zdefiniować typ indeksu, jak również wartości.

Przykład: Type of Array

Copy

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

W powyższym przykładzie interfejs NumList definiuje typ tablicy z indeksem jako liczba i wartością jako typ liczbowy. W ten sam sposób, IStringList definiuje tablicę typu string z indeksem jako string i wartością jako string.

Właściwości opcjonalne

Czasami możemy zadeklarować interfejs z nadmiarem właściwości, ale nie możemy oczekiwać, że wszystkie obiekty będą definiować wszystkie podane właściwości interfejsu. Możemy mieć właściwości opcjonalne, oznaczone znakiem „?”. W takich przypadkach obiekty interfejsu mogą, ale nie muszą definiować tych właściwości.

Przykład: Optional Property

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"}

W powyższym przykładzie empDept jest oznaczony symbolem ?, więc obiekty IEmployee mogą, ale nie muszą zawierać tej właściwości.

Właściwości tylko do odczytu

TypeScript zapewnia sposób oznaczania właściwości jako tylko do odczytu. Oznacza to, że gdy właściwości zostanie przypisana wartość, nie można jej zmienić!

Przykład: Readonly Property

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

W powyższym przykładzie właściwość SSN jest tylko do odczytu. Definiujemy obiekt personObj typu Citizen i przypisujemy wartości dwóm właściwościom interfejsu. Następnie spróbujemy zmienić wartości przypisane obu właściwościom –name i SSN. Kompilator TypeScript wyświetli błąd, gdy spróbujemy zmienić właściwość SSN tylko do odczytu.

Rozszerzanie interfejsów

Interfejsy mogą rozszerzać jeden lub więcej interfejsów. To sprawia, że pisanie interfejsów jest elastyczne i wielokrotnego użytku.

Przykład: Extend Interface

Copy

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

W powyższym przykładzie interfejs IEmployee rozszerza interfejs IPerson. Zatem obiekty IEmployee muszą zawierać wszystkie właściwości i metody interfejsu IPerson, w przeciwnym razie kompilator wyświetli błąd.

Implementacja interfejsu

Podobnie do języków takich jak Java i C#, interfejsy w TypeScript mogą być implementowane za pomocą klasy. Klasa implementująca interfejs musi być ściśle zgodna ze strukturą interfejsu.

Przykład: Implementacja interfejsu

Kopia

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");

W powyższym przykładzie interfejs IEmployee jest implementowany w klasie Employee za pomocą słowa kluczowego the implement. Klasa implementująca powinna ściśle zdefiniować właściwości i funkcję o tej samej nazwie i typie danych. Jeśli klasa implementująca nie podąża za strukturą, wtedy kompilator pokaże błąd.

Oczywiście klasa implementująca może zdefiniować dodatkowe właściwości i metody, ale przynajmniej musi zdefiniować wszystkich członków interfejsu.

W następnym rozdziale dowiemy się więcej o klasach TypeScript.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.