我是打字稿的新手,我不了解构造函数接口以及它们的类型检查方式。以下是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);
以下是关于上述代码的文档:
因为createClock的第一个参数是ClockConstructor类型,所以 createClock(AnalogClock,7,32),它检查AnalogClock有 正确的构造函数签名。
现在这实际上意味着DigitalClock类或AnalogClock类具有ClockConstructor接口定义的类型。怎么样?它是一个类,接口描述了一个构造函数。
欢迎任何参与者?
答案 0 :(得分:2)
让我们从您的示例中的简单界面开始:
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>;
}
(定义因使用ES5
或ES6
目标而异,具体取决于ES5
目标。
正如您所看到的,界面定义了不同的构造函数签名,prototype
和isArray
函数,就像您使用它一样:
Array.isArray([1,2])
如果您没有能力为类本身(而不是实例)提供接口,那么您将无法使用此isArray
函数,因为这是错误的:
let a = [];
a.isArray(3);
类DigitalClock
和AnalogClock
通过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);
(其中ctor
为ClockConstructor
)与new DigitalClock(hour, minute)
类似(只是更通用)。