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 - 在 NestJs 中,如何根据其接口(interface)注入(inject)服务?

javascript - Extjs 将 xml 文件属性加载到存储中

javascript - 维基百科 API 上的 CORS 错误

javascript - SVG路径半圆中的圆 Angular

javascript - 点击后用链接替换 anchor 文本

Java 泛型 : why can't inner interface implement from a (inner) superinterface?

php - 简单的 jQuery - php 通信

interface - 通过 Go 中的接口(interface)解耦......接口(interface)实现者的一部分?

reactjs - typescript 使用字符串或字符串[]

xml - 将外部文件中的原始 XML 嵌入到 Typescript 文件中