typescript类类型-实例部分与静态部分详解

4,572 阅读3分钟

当这个我们操作一个类接口的时候呢,我们必须要知道类实际上是有两个类型的:

静态部分类型实例部分类型

那么什么是实例部分与静态部分?

我们先看一下下面的代码,以官方的代码来讲解:

interface ClockInterface {
    currentTime: Date;
    setTime(d: Date);
}

class Clock implements ClockInterface {
    currentTime: Date;
    setTime(d: Date) {
        this.currentTime = d;
    }
    constructor(h: number, m: number) { }
}

实例部分类型

比如,在这个例子中,下面的接口中的currentTimesetTime就是实例的类型

interface ClockInterface {
    currentTime: Date;
    setTime(d: Date);
}

实例类型通常是指那些通过Clock这个类实例出来的对象,要满足的部分。

放到这里的意思就是:我们通过new Clock()出来的实例,必须要满足拥有currentTimesetTime这两个属性。


静态部分类型

上面官方的例子中,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 实例化出来的对象(类的实例部分)应该满足这个接口的规则


参考

typescript官方

blog