Interface trong Typescript (Phần 1)



  • Giới thiệu:
    Interface trong typescript cho phép bạn định nghĩ thuộc tính là gì và phương thức là gì mà đối tượng cần để được thực thi (implement). Nếu đối tượng tuân thủ đúng khuôn mẫu interface thì đối tượng đã implement interface ấy sẽ được thi hành đúng. Nếu interface không được thi hành đúng đắn thì typescript sẽ phát sinh lỗi ngay lập tức. Để rõ hơn, bạn hãy xem những ví dụ và giải thích dưới đây:

    1. Bắt đầu với interface đầu tiên:

       function printLabel(labelObj: { label: string,size: number }) 
       {
       console.log("Label: " + labelObj.label + " - Size: " + labelObj.size); 
       } 
       let _object = {size: 10, label: "Size 10 Object", _size:1000}; 
       printLabel(_object);
      

    Đây là một ví dụ không sử dụng interface. Chương trình sẽ tiến hành gọi hàm printLabel. Hàm printLabel sẽ yêu cầu hai tham số là label và size. Hàm sẽ yêu cầu label là kiểu string và size là kiểu number. Nếu bạn truyền sai kiểu, hàm sẽ không chạy được. Nhưng lưu ý rằng đối tượng object truyền vào có thể có nhiều thuộc tính nhưng trình biên dịch chỉ kiểm tra hai thuộc tính size và label mà hàm printLabel yêu cầu.
    Dưới đây, bạn có thể tạo lại một hàm như trên sử dụng interface. Interface mô tả yêu cầu hai thuộc tính label và size:

    interface LabelValue {
    label: string;
    size: number;
    }
    
    function printLabel1(labelObj: LabelValue) {
        console.log("Label: " + labelObj.label + " - Size: " + labelObj.size); 
    }
    
    let _object = {size: 10, label: "Size 10"};
    printLabel1(_object);
    

    Bạn có thể sử dụng Interface LabelValue để mô tả ví dụ trước. Nó vẫn còn hai thuộc tính size và Label.

    1. Optional Properties
      Xem ví dụ

      interface CircleConfig {
       color?: string;
       radius?: number;
       diameter?:number;
      }
      
      function createCircle(config: CircleConfig): {color: string; radius: number; diameter:number} {
      let newCircle = {color: "white", radius: 100, diameter: 1000};
      
      if (config.color) {
           newCircle.color = config.color;
      }
      if (config.diameter) {
          newCircle.diameter = 2 * config.radius;
      }
      return newCircle;
      }
      
      let circle = createCircle({color: "black", radius:150, diameter:1});
      console.log("diameter: " + circle.diameter);
      

    Kết quả: In ra console với diameter: 300

    Interface sử dụng linh hoạt các thuộc tính nghĩa là đối tượng truyền vào có thể không cần truyền hết tham số yêu cầu, cái nào cần truyền thì truyền cái đó. Với việc thêm dấu ? sau tên thuộc tính của interface, ta đã sử dụng optional properties, có thể linh hoạt trong việc ghi thuộc tính cho đối tượng.

    1. Thuộc tính readonly (chỉ đọc )
      Có một số thuộc tính không cho phép chỉnh sửa khi đối tượng khởi tạo. Bạn có thể đặt readonly trước tên thuộc tính.
      Ví dụ:

      interface Point 
      { 
        readonly x: number; 
        readonly y: number; 
      }
      

    Bạn có thể xây dựng đối tượng Point bằng cách gán một đối tượng. Và sau khi gán ta không thể thay đổi giá trị thuộc tính.

    let p1: Point = { x: 10, y: 20 };
    p1.x = 5; // error!
    

    Và đối với mảng, bạn cũng không thể chỉnh sửa thuộc tính với ReadonlyArray<T>. Một kiểu dữ liệu giống như Array<T> nhưng tất cả các hàm biến đổi trong mảng đều được loại bỏ nên không thể thay dổi được giá trị.

    let num: number[] = [1, 2, 3, 4];
    let readOnlyNumber: ReadonlyArray<number> = num;
    readOnlyNumber [0] = 12; // error! 
    readOnlyNumber.push(5); // error! 
    readOnlyNumber.length = 100; // error! 
    num = readOnlyNumber; // error!
    
    1. Như vậy giữa const và readonly có sự khác nhau gì không?
      Cả hai từ khóa const và readonly đều trả lời cho câu hỏi liệu cái nào sử dụng cho biến và cái nào sử dụng cho thuộc tính. Thật vậy, const được khai báo hằng số cho biến và readonly được sử dụng khai báo thuộc tính chỉ đọc.

    2. Function Types
      Ví dụ:

      interface SearchFunc {
        (source: string, subString: string): boolean;
      }
      
      let search: SearchFunc;
      search = function(source: string, subString: string) {
           let result = source.search(subString);
       return result > -1;
      }
      console.log(search("Nguyen Van A","Nguyen")); // return true
      

    Mô tả một hàm trong một interface giống như việc khai báo hàm với danh sách thuộc tính và trả về một kiểu dữ liệu.

    Xem tiếp phần 2


Log in to reply