TypeScript中Interface的理解

背景

在閱讀官方文檔的時候,遇到了如下代碼。

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

當時就很疑惑,爲什麼這樣的代碼是合法的。主要的問題是,createClock的第一個參數要求的是ClockConstructor,而DigitalClock和AnalogClock這兩個類都是由ClockInterface這一接口繼承來的,並沒有實現ClockConstructor,按照我的理解,這樣的代碼很顯然是不合法的。但這段代碼無疑又是正確的,畢竟這是官方示例,又能編譯運行通過。

對於Interface的理解

既然是官方的示例,還是要從官方文檔入手理解。在官方文檔對Interface的介紹中第一句就寫到:“One of TypeScript’s core principles is that type-checking focuses on the shape that values have. ”,也就是說,TypeScript的核心原則是對值的“形狀”進行檢查。這裏的值的形狀就是指他所擁有的屬性和方法。
分析createClock的第一個參數,ctor: ClockConstructor,在TypeScript,他的意思是第一個參數要和ClockConstructor這一Interface的形狀一樣。什麼叫形狀一樣?就是要有相同的屬性和方法。那ClockConstructor有且只有一個構造方法即new (hour: number, minute: number): ClockInterface(我得吐槽一下Interface的構造方法爲啥不也用constructor啊看起來好不自然啊。)。也就是說,只要你提供一個構造器接受兩個數字作爲參數,同時構造完成一個符合ClockInterface形狀的對象,那就是符合要求的。
如果這一想法是正確的,那如下的代碼應該也能夠工作:

class someClock {
    constructor(a: number, b: number) {}
    tick() {}
}

let testClock = createClock(someClock, 8, 12)

someClock並未聲明implements ClockInterface,但也能被createClock所接受,這也證明了之前的想法,他的要求是參數列表和返回值類型能對的上,達到這個要求就可以被接受。

總結

會產生這樣的問題,還是因爲把其他語言的思路往TypeScript上套了。例如在JAVA中,如果採用類似的實現,那麼只有顯式聲明瞭implements ClockInterface的類才能被creatClock方法所接受。但解決問題還是要從官方文檔入手,理解了“TypeScript的核心原則之一是對值所具有的結構進行類型檢查”這句話,才能更好地學習TypeScript。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章