簡體   English   中英

理解打字稿中的構造函數接口

[英]Understanding Constructor Interfaces in typescript

我是打字稿的新手,我不了解構造函數接口以及它們的類型檢查方式。 以下是docs的片段:

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

以下是doc對上述代碼的說法:

因為createClock的第一個參數是ClockConstructor類型,所以在createClock(AnalogClock,7,32)中,它檢查AnalogClock是否具有正確的構造函數簽名。

現在這實際上意味着DigitalClock類或AnalogClock類具有ClockConstructor接口定義的類型。 怎么樣? 它是一個類,接口描述了一個構造函數。

請接受任何參賽者?

讓我們從您的示例中的簡單界面開始:

interface ClockInterface {
    tick();
}

此接口定義此類型的實例包含tick方法,這兩個實現此接口:

class MyClock implements ClockInterface {
    public tick(): void {
        console.log("tick");
    }
}

let a: ClockInterface = new MyClock();
let b: ClockInterface = {
    tick: () => console.log("tick")
}

這是非常直接的,因為類實現與其他OO語言相同,第二個實現不是那么簡單,但對於javascript開發人員來說應該很容易理解。

這很棒! 但是如果我想獲得一個類的構造函數作為我的函數的參數會發生什么?
這不起作用:

function constructorClock(ctor: ClockInterface): ClockInterface {
    return new ctor();
}

這里的參數是ClockInterface一個實例,而不是類(/構造函數),所以為了處理這樣的場景,我們可以為類本身而不是實例定義一個接口:

interface ClockConstructor {
    new (hour: number, minute: number): ClockInterface;
}

現在我們可以擁有這個功能:

function constructorClock(ctor: ClockConstructor): ClockInterface {
    return new ctor(3, 5);
}

這些構建器接口給我們的另一個問題是能夠定義靜態類成員/方法,一個很好的例子是ArrayConstructor (它是lib.d.ts一部分):

interface ArrayConstructor {
    new (arrayLength?: number): any[];
    new <T>(arrayLength: number): T[];
    new <T>(...items: T[]): T[];
    (arrayLength?: number): any[];
    <T>(arrayLength: number): T[];
    <T>(...items: T[]): T[];
    isArray(arg: any): arg is Array<any>;
    prototype: Array<any>;
}

(定義因您使用ES5ES6目標而異,這是ES5目標)。

正如您所看到的,接口定義了不同的構造函數簽名, prototypeisArray函數,就像您使用它一樣:

Array.isArray([1,2])

如果您沒有能力為類本身(而不是實例)提供接口,那么您將無法使用此isArray函數,因為這是錯誤的:

let a = [];
a.isArray(3);

DigitalClockAnalogClock實施ClockInterface通過具有tick方法(即它們的實例將具有該方法),但它們實現的ClockConstructor與它們的界面constructor函數,它被用於與new並返回的一個實例ClockInterface

希望這有助於澄清它


編輯

構造函數當然不返回interface ,它返回一個實現此ClockInterface接口的實例。
也許這會讓它變得更容易:

class BaseClock {
    protected hour: number;
    protected minute: number;

    constructor(hour: number, minute: number) {
        this.hour = hour;
        this.minute = minute;
    }

    public tick() {
        console.log(`time is: ${ this.hour }:${ this.minute }`);
    }
}

class DigitalClock extends BaseClock {
    constructor(hour: number, minute: number) {
        super(hour, minute);
    }

    tick() {
        console.log("digitial");
        super.tick();
    }
}

class AnalogClock extends BaseClock {
    constructor(hour: number, minute: number) {
        super(hour, minute);
    }

    tick() {
        console.log("analog");
        super.tick();
    }
}

interface ClockConstructor {
    new (hour: number, minute: number): BaseClock;
}

function createClock(ctor: ClockConstructor, hour: number, minute: number): BaseClock {
    return new ctor(hour, minute);
}

我們現在只使用類,而不是接口,這更有意義嗎?

語法: new (hour: number, minute: number): ClockInterface定義了一個構造函數,這個:

function createClock(ctor: ClockConstructor, hour: number, minute: number): ClockInterface {
    return new ctor(hour, minute);
}

createClock(DigitalClock, 12, 17);

就好像:

function createDigitalClock(hour: number, minute: number): ClockInterface {
    return new DigitalClock(hour, minute);
}

createDigitalClock(12, 17);

new ctor(hour, minute); (其中ctorClockConstructor )就像new DigitalClock(hour, minute) (只是更通用)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM