openplanning

Interface trong TypeScript

  1. Interface là gì?
  2. Interface là một kiểu dữ liệu
  3. Trường tuỳ chọn
  4. Trường chỉ đọc (Read-only)
  5. Interface mở rộng từ các interface khác
  6. Thi hành các interface
  7. Function-Type Interface
  8. Array-Type Interface

1. Interface là gì?

Trong TypeScript, interface là một cấu trúc khai báo các tiêu chuẩn. Các lớp được dẫn xuất (derived) từ một interface phải tuân thủ các tiêu chuẩn do interface đặt ra.
Không có khái niệm interface trong JavaScript, vì vậy trình biên dịch TypeScript không chuyển đổi các interface sang JavaScript. Interface được sử dụng như một công cụ để kiểm tra các kiểu trong chương trình.
TypeScript sử dụng từ khoá interface cho việc định nghĩa một interface. Interface có thể bao gồm các trường (field), các property và các phương thức (method).
interface Greeting {
   name: string;

   sayHello(friendName:string): string; // A method

   sayBye: (friendName: string) => string; // A arrow method
}
Trong ví dụ trên, Greeting là một interface nó bao gồm 1 trường (field) và 2 phương thức.
  • name: Một trường (field) với kiểu dữ liệu là string.
  • sayHello: Một phương thức thông thường với một tham số kiểu string, và trả về một string.
  • sayBye: Một phương thức Lambda với một tham số kiểu string, và trả về một string. (Phương thức Lambda cũng còn được gọi là các phương thức mũi tên).

2. Interface là một kiểu dữ liệu

Interface là một kiểu dữ liệu, và bạn có thể tạo ra các đối tượng một cách trực tiếp, các đối tượng được tạo ra phải thi hành (implements) tất cả các trường, các property và các phương thức được khai báo trong interface.
Để đơn giản hãy xem ví dụ:
interface_ex1.ts
interface Greeting {
    name: string;
    sayHello(friendName: string): string; // A method
    sayBye: (friendName: string) => string; // A arrow method
}
function interface_ex1_test() {
    // Create an object:
    var enPerson1: Greeting = {
        name: "John",
        sayHello: function (friendName: string): string {
            return "Hello " + friendName;
        },
        sayBye: function (friendName: string): string {
            return "Good Bye";
        }
    };
    // Create an object
    var vnPerson1: Greeting = {
        name: "Tran",
        sayHello: function (friendName: string): string {
            return "Xin Chao " + friendName;
        },
        sayBye: function (friendName: string): string {
            return "Tam biet " + friendName;
        }
    };
    // Test objects:
    console.log(enPerson1.name); // John
    console.log(enPerson1.sayHello("Tom")); // Hello Tom

    console.log(vnPerson1.name); // Tran
    console.log(vnPerson1.sayBye("Jerry")); // Tam Biet Jerry
}
interface_ex1_test(); // Call the function.
Output:
John
Hello Tom
Tran
Tam biet Jerry
Khi tạo một đối tượng trực tiếp từ một interface bạn phải tuân thủ quy tắc Key-Value. Điều này có nghĩa là tất cả các thành viên trong đối tượng này đều được viết theo quy tắc Key-Value (Khoá và giá trị).
// Create an object:
var enPerson1: Greeting = {
    name: "John",
    sayHello: function (friendName: string): string {
        return "Hello " + friendName;
    },
    sayBye: function (friendName: string): string {
        return "Good Bye";
    }
};

3. Trường tuỳ chọn

Trong TypeScript, các trường của một interface có thể được định nghĩa như một tuỳ chọn, điều này có nghĩa là lớp hoặc đối tượng thi hành interface này có thể bỏ qua chúng.
interface Interface_Name  {
   optional_field_name? data_type;
   // Other fields and methods (If any)
}
Trong ví dụ dưới đây, trường empDept là một tuỳ chọn.
interface_optional_field_ex1.ts
interface IEmployee {
    empCode: number;
    empName: string;
    empDept?: string;
}
function interface_optional_field_ex1_test() {
    let tom: IEmployee = {
        empCode: 1,
        empName: "Tom"
    }
    let jerry: IEmployee = {
        empCode: 2,
        empName: "Jerry",
        empDept: "IT"
    }
    console.log(" --- tom --- ");
    console.log('tom.empName: ' + tom.empName); // Tom
    console.log('tom.empDept: ' + tom.empDept); // undefined
    console.log(" --- jerry --- ");
    console.log('jerry.empName: ' + jerry.empName); // Jerry
    console.log('jerry.empDept: ' + jerry.empDept); // IT
}
interface_optional_field_ex1_test(); // Call the function.
Output:
--- tom ---
tom.empName: Tom
tom.empDept: undefined
 --- jerry ---
jerry.empName: Jerry
jerry.empDept: IT

4. Trường chỉ đọc (Read-only)

TypeScript cung cấp một cách để đánh dấu một trường là chỉ đọc (read only). Điều này có nghĩa là một khi trường được gán một giá trị, nó không thể thay đổi được!
Trong ví dụ dưới đây, trường SSN là chỉ đọc. Một khi nó được gán giá trị, bạn không thể gán giá trị khác cho nó, trình biên dịch sẽ thông báo lỗi nếu bạn vi phạm điều đó.
interface_readonly_field_ex1.ts
interface Citizen {
    name: string;
    readonly SSN: number;
}
function interface_readonly_field_ex1_test() {
    let personObj: Citizen = {
        SSN: 11111,
        name: 'Tom'
    };
    personObj.name = 'Jerry'; // OK
    personObj.SSN = 22222; // Compiler Error (!!!!!)
}  
interface_readonly_field_ex1_test(); // Call the function.

5. Interface mở rộng từ các interface khác

Trong TypeScript, một interface có thể mở rộng (extends) từ một hoặc nhiều interface khác theo cú pháp:
interface C extends A, B {
   // codes..
}
Ví dụ:
interface_extends_ex1.js
interface IAnimal {
    name: string;
}
interface ICat extends IAnimal {
    age: number;
    move(): void;
}
function interface_extends_ex1_test() {
    let tom = {
        name: "Tom",
        age: 3,
        move: function () {
            console.log("Moving...");
        }
    };
    console.log(`Name: ${tom.name}`);
    console.log(`Age: ${tom.age}`);
    tom.move();
}
interface_extends_ex1_test(); // Call the function.
Output:
Name: Tom
Age: 3
Moving...

6. Thi hành các interface

Cũng giống như JavaC#. Interface trong TypeScript có thể được thi hành (implement) bởi một lớp. Về cơ bản, một lớp có thể thi hành một hoặc nhiều interface, và nó phải tuân thủ cấu trúc được định nghĩa bởi tất cả các interface đó.

7. Function-Type Interface

TypeScript cũng có khái niệm về Functional Interface như trong Java. Chúng ta tạm gọi nó là Function-Type Interface - Một interface chỉ có duy nhất một phương thức, và phương thức này không có tên, nó chỉ bao gồm các tham số và kiểu trả về. Function-Type Interface được sử dụng như một hàm, đôi khi nó cũng có các trường tuỳ chọn.
Cú pháp định nghĩa Functional Interface:
interface Interface_Name  {
     (param_name_1 data_type_1, param_name_n data_type_n): return_data_type;
}
Function-Type Interface là interface đặc biệt, nó được sử dụng như một hàm chứ không phải là một kiểu dữ liệu.
Việc viết một interface mở rộng từ một Function-Type Interface là không có nhiều ý nghĩa.
Hoặc việc viết một lớp thi hành một Function-Type Interface là không thể.
Ví dụ:
interface IFormatter {
    (text:string) : number;
}
Functional interface được sử dụng như một hàm. Hãy xem ví dụ sau:
functional_interface_ex1.js
interface IFormatter {
    (text:string) : number;
}
function functional_interface_ex1_test()  {
   var intFormatter: IFormatter = function(text:string): number {
       return parseInt(text);
   }
   var floatFormatter: IFormatter = function(text:string): number {
       return parseFloat(text);
   }
   var text:string = "2001.55";

   var value1 = intFormatter(text); // Use as a function
   console.log(value1);  // 2001
   var value2 = floatFormatter(text); // Use as a function
   console.log(value2);  // 2001.55
} 
functional_interface_ex1_test(); // Call the function.
Output:
2001
2001.55
Function-Type Inteface có thể bao gồm các trường tuỳ chọn, hãy xem ví dụ:
functional_interface_ex2.ts
interface IFormatter {
    (text:string) : number;
    description? : string;
}
function functional_interface_ex2_test()  {
   var intFormatter: IFormatter = function(text:string): number {
       return parseInt(text);
   }  
   intFormatter.description = "Format a string to integer";
  
   var text: string = "2001.55";
   var result = intFormatter(text); // Use as a function
   console.log(intFormatter.description);  // Format a string to integer
   console.log(result);  // 2001  
}
functional_interface_ex2_test(); // Call the function.
Output:
Format a string to integer
2001

8. Array-Type Interface

TypeScript cung cấp một loại interface để mô phỏng một mảng, nó được gọi nó là Array-Type Interface.
Cú pháp:
interface Interface_Name  {
    [index_name_1: index_data_type_1] : value_data_type;
    [index_name_n: index_data_type_n] : value_data_type;
    // Other properties and methods (If any) ...
}
Chú ý: index_data_type_1,..., index_data_type_n phải khác nhau, nếu không bạn sẽ nhận được một thông báo lỗi:
Duplicate index signature for type 'xxx'
Ví dụ:
interface_array_ex1.ts
interface IEmployeeSalary {
    [emp_name:string]:number; // emp_name --> salary
}
function interface_array_ex1_test()  {
    var salaryMap : IEmployeeSalary = {};

    salaryMap["Tom"] = 2000;  
    salaryMap["Jerry"] = 1500;  
    salaryMap["Donald"] = 3000;  

    console.log(salaryMap["Jerry"]); // 1500  
}
interface_array_ex1_test(); // Call the function.
Ví dụ: Một Array-Type Interface với index_data_typenumber.
interface_array_ex2.ts
interface IFootballerArray {
    [index:number]:string;
}
function interface_array_ex2_test()  {
    var footballerArray : IFootballerArray = ["Ronaldo", "Messi", "Pele"];

    console.log(footballerArray[0]); // Ronaldo
    console.log(footballerArray[1]); // Messi

    footballerArray[0.5] = "<Funny>";
    console.log(footballerArray[0.5]); // <Funny>
}
interface_array_ex2_test(); // Call the function.
Output:
Ronaldo
Messi
<Funny>
Ví dụ: Một Array-Type Interface với các trường và các phương thức:
interface_array_ex2b.ts
interface IFootballPlayerArray {
    description: string;
    someMethod(): string;
    [index: number]: string;
}
function interface_array_ex2b_test() {
    var footballerArray: IFootballPlayerArray = {
        description: "Famous Football Players",
        someMethod: function (): string {
            return "Something";
        }
    }
    footballerArray[0] = "Ronaldo";
    footballerArray[1] = "Messi";
    footballerArray[2] = "Pele";
    footballerArray[0.5] = "<Funny>";

    console.log(footballerArray.description); // Famous Football Players
    console.log(footballerArray.someMethod()); // Something
    console.log(" --- "); //  ---
    console.log(footballerArray[0]); // Ronaldo
    console.log(footballerArray[1]); // Messi
    console.log(footballerArray[0.5]); // <Funny>
}
interface_array_ex2b_test(); // Call the function.
Output:
Famous Football Players
Something
 ---
Ronaldo
Messi
<Funny>
Ví dụ: Một Array-Type Interface với 2 chiều chỉ số (2 dimensional indexes):
interface_array_2d_ex1.ts
interface IStaff {
    [staff_id:number] : number; // staff_id --> salary
    [staff_number:string] : number; // staff_number --> salary
}
function interface_array_2d_ex1_test()  {
    var staffArray : IStaff = {};

    staffArray[100] = 2000;  
    staffArray[101] = 1500;  
    staffArray[102] = 3000;  

    staffArray["S-100"] = 2000;  
    staffArray["S-101"] = 1500;  
    staffArray["S-102"] = 3000;  

    console.log(staffArray[100]); // 2000  
    console.log(staffArray[102]); // 3000  
    console.log(" --- ");  
    console.log(staffArray["S-100"]); // 2000  
    console.log(staffArray["S-102"]); // 3000  
}
interface_array_2d_ex1_test(); // Call the function.
Output:
2000
3000
 ---
2000
3000