javascript - 理解 typescript 中的构造函数接口(interface)

标签 javascript interface typescript

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

这是文档对上述代码的描述:

Because createClock’s first parameter is of type ClockConstructor, in createClock(AnalogClock, 7, 32), it checks that AnalogClock has the correct constructor signature.

现在这实际上意味着 DigitalClock 类或 AnalogClock 类具有由 ClockConstructor 接口(interface)定义的类型。如何?它是一个类,接口(interface)描述了一个构造函数。

请问有人要吗?

最佳答案

让我们从示例中的简单界面开始:

interface ClockInterface {
    tick();
}

该接口(interface)定义了该类型的实例包含tick方法,这两个实现了该接口(interface):

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)而不是实例:

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

现在我们可以拥有这个功能:

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

这些构建器接口(interface)给我们带来的另一个问题是能够定义静态类成员/方法,一个很好的例子是 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>;
}

(定义取决于您使用的是 ES5 还是 ES6 目标,这是 ES5 目标)。

如您所见,接口(interface)定义了不同的构造函数签名,prototypeisArray 函数,您可以像这样使用它:

Array.isArray([1,2])

如果您没有能力为类本身(而不是实例)提供接口(interface),那么您将无法使用此 isArray 函数,因为这是错误的:

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

DigitalClockAnalogClock 类通过 tick 方法(即它们的 instances 有这个方法),但是他们用他们的 constructor 函数实现了 ClockConstructor 接口(interface),这个函数与 new 一起使用,它返回ClockInterface 的实例。

希望这有助于澄清它


编辑

构造器当然不会返回一个interface,它返回一个实现了这个ClockInterface接口(interface)的实例。
也许这会让事情变得更容易:

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

我们现在只使用类而不是接口(interface),这样更有意义吗?

语法:new (hour: number, minute: number):ClockInterface定义了一个构造函数,this:

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) (只是更通用)。

关于javascript - 理解 typescript 中的构造函数接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37292534/

相关文章:

javascript - 优惠券验证

javascript - 在 Javascript 中移动字符串

javascript - Angular JS - 添加一个 jquery 插件到 jQlite

c# - 将 Dictionary<Key, Value> 转换为 IReadOnlyDictionary<Key, IValue>?

c# - 什么是阅读 ISomething : ISomethingElse 的正确方法

javascript - JavaScript 文件顶部的 "format register"字符串是什么?

javascript - 如何使用 JQuery 更改 onClick 复选框的值?

c# - 根据绑定(bind)的 View 模型实例显示 ui 控件

typescript - 如何使用 RootState 修复切片的循环依赖关系?

typescript - 获取包含所有字符串枚举值的联合类型