当这个我们操作一个类接口的时候呢,我们必须要知道类实际上是有两个类型的:
静态部分类型
和实例部分类型
那么什么是实例部分与静态部分?
我们先看一下下面的代码,以官方的代码来讲解:
interface ClockInterface {
currentTime: Date;
setTime(d: Date);
}
class Clock implements ClockInterface {
currentTime: Date;
setTime(d: Date) {
this.currentTime = d;
}
constructor(h: number, m: number) { }
}
实例部分类型
比如,在这个例子中,下面的接口中的currentTime
、setTime
就是实例的类型。
interface ClockInterface {
currentTime: Date;
setTime(d: Date);
}
实例类型通常是指那些通过Clock
这个类实例出来的对象,要满足的部分。
放到这里的意思就是:我们通过new Clock()
出来的实例,必须要满足拥有currentTime
、setTime
这两个属性。
静态部分类型
上面官方的例子中,class里的构造器是静态类型
:
constructor(h: number, m: number) { }
我们知道了什么是静态部分、什么是实例部分,那么两者在typescript有什么要注意的地方呢?
当我们的类,去实现一个构造器的接口(静态类型的接口)的,实际上会报错的。
换句话来说,就是类不能
直接去实现静态部分的接口,但可以直接实现实例类型的接口
我们看一下下面的例子:
// 有new,就是有构造器签名,就是静态类型的接口,所以不能被类直接实现,会报错
interface ClockConstructor {
new (hour: number, minute: number);
}
class Clock implements ClockConstructor {
currentTime: Date;
constructor(h: number, m: number) { }
}
报错是因为,当一个类去实现一个接口的时候,它实际上是对实例部分做类型检查,比如currentTime
或者setTime
而构造器存在于类的静态部分,所以是不会做检查的。
所以一个类相关的接口,就是实例部分的接口和构造器的接口(静态部分接口)
当一个类去实现一个实例部分接口的时候,就实现了对实例部分的类型检查,但是此时是没有对静态部分(构造器部分)进行类型检查的。
那么问题来了:
如果我们就是要对类的静态部分,比如类的构造函数进行检查的话,怎么办呢?
如何用类类型接口(静态部分),什么时候用实例接口?
上面我们说到当一个类去实现一个接口的时候,它实际上是对实例部分做类型检查。
所以如果我们就是要对,静态部分去做检查的时候,就要像下面那样写。
// 静态部分接口
interface ClockConstructor {
new (hour: number, minute: number): ClockInterface;
}
// 实例部分接口
interface ClockInterface {
tick();
}
// 第一个参数ctor的类型是接口 ClockConstructor,在这里就为类的静态部分指定需要实现的接口
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 toc");
}
}
let digital = createClock(DigitalClock, 12, 17);
let analog = createClock(AnalogClock, 7, 32);
在上面的代码中
function createClock(ctor: ClockConstructor, hour: number, minute: number): ClockInterface {
return new ctor(hour, minute);
}
上面的例子中,我们创建了一个函数createClock
。
这个函数的第一个参数ctor的类型是接口 ClockConstructor,这样就实现了对类的静态部分实现类型检查
最后对inplements的理解对一点补充
class AnalogClock implements ClockInterface {
constructor(h: number, m: number) { }
tick() {
console.log("tick tock");
}
}
这里的implements ClockInterface
这个意思不是AnalogClock本身(类的静态部分)应该符合接口规则
而是类 AnalogClock 实例化出来的对象(类的实例部分)应该满足这个接口的规则