12/08/2018, 14:51

Interface trong Typescript (Phần 2)

Tôi xin viết tiếp theo bài Interface trong Typescript (Phần 1): 6. Indexable Types Giống như việc làm thế nào để mô tả kiểu dữ liệu của hàm, bạn có thể mô tả kiểu dữ liệu rằng chúng ta có thể gán chỉ số như subName[0], num[10],… Kiểu dữ liệu chỉ mục giúp bạn có thể gán chỉ mục cho ...

Tôi xin viết tiếp theo bài Interface trong Typescript (Phần 1):

6. Indexable Types

Giống như việc làm thế nào để mô tả kiểu dữ liệu của hàm, bạn có thể mô tả kiểu dữ liệu rằng chúng ta có thể gán chỉ số như subName[0], num[10],… Kiểu dữ liệu chỉ mục giúp bạn có thể gán chỉ mục cho đối tượng, và trả về kiểu dữ liệu tương ứng.

Ví dụ:

interface StringArray {
    [index: number]: string;
}

let myName: StringArray;
myName = ["Tôi", "là","Nguyễn","Văn","A"];

let myStr: string = myName[0];
console.log(myStr);

Xem tiếp một ví dụ để cụ thể hơn:

class Animal {
    name: string;
    constructor(name: string) {
       this.name = name;
    }
}
class Dog extends Animal {
    breed: string;
    constructor(name: string,breed: string) {
       super(name);
       this.breed = breed;
    }
}

interface NotOkay {
//  Error: indexing with a 'string' will sometimes get you a Dog!
//  [x: string]: Animal;
    [x: number]: Dog;
}


let _dog1 = new Dog("Dog","Husky");
let _dog2 = new Dog("Dog","Alaska");
let _dog3 = new Dog("Dog","Golden");


let ani: NotOkay;
ani = [_dog1, _dog2, _dog3];

for (let index in ani)
{
    console.log("Animal: " + ani[index].name + " - breed" + ani[index].breed);
}

Một trường hợp khác, sử dụng từ khóa readonly để ngăn cản sự thay đổi dữ liệu của mảng.

VD:

interface ReadonlyStringArray {
    readonly [index: number]: string;
}
let myArray: ReadonlyStringArray = ["Alice", "Bob"];
console.log(myArray[1]);
myArray[1] = "Mallory"; // error!

Lưu ý: Khi kiểu dữ liệu của chỉ số trùng với kiểu dữ liệu của thuộc tính thì chương trình sẽ sinh ra lỗi.

Ví dụ:

interface NumberDictionary
 {
 [index: string]: number;
 length: number; // ok, length is a number 
name: string; // lỗi, kiểu dữ liệu của 'name' trùng với kiểu dữ liệu của index
 }

7. Class Types

Ở đây lớp được sử dụng như một kiểu dữ liệu

Ví dụ:

interface ClockConstructor 
{ 
    new (hour: number, minute: number): ClockInterface; 
} 
interface ClockInterface 
{ 
    tick(); 
} 
function createClock(ctor: ClockConstructor, hour: number, minute: number): ClockInterface 
{
     return new ctor(hour, minute); 
} 
class DigitalClock implements ClockInterface { 
    constructor(h: number, m: number) { } 
    tick() { 
        console.log("beep beep"); 
    } 
} 
class AnalogClock implements ClockInterface { 
    constructor(h: number, m: number) { } 
    tick()
    { 
        console.log("tick tock"); 
    } 
} 
let digital = createClock(DigitalClock, 12, 17); 
let analog = createClock(AnalogClock, 7, 32);

8. Extending Interfaces

Giống lớp, interface có thể kế thừa từ những interface khác.

Ví dụ:

interface Shape 
{
 color: string;
 }
 interface PenStroke
 {
 penWidth: number; 
}
 interface Circle extends Shape, PenStroke
 {
 sideRadius: number;
 }
 let circle  =  < Circle >{};
 circle .color = "blue";
 circle . sideRadius = 10;
 circle .penWidth = 5.0; 

9. Kiểu hỗn hợp (Hybrid Types)

Interface có thể mô tả được nhiều kiểu dữ liệu trong thế giới thực. Do tính linh hoạt và năng động của javascript, đôi khi bạn có thể gặp một đối tượng hoạt động như một sự kết hợp của số kiểu dữ liệu khác.

Ví dụ:

interface Counter
 {
     (start: number): string;
     interval: number;
     reset(): void;
 }
 function getCounter(): Counter
 {
     let counter = <Counter>function (start: number) { };
     counter.interval = 123;
     counter.reset = function () { };
     return counter; 
} 
let c = getCounter(); 
c(10);
c.reset();
c.interval = 5.0;
0