TypeScript-interface进阶-高级

1,393 阅读4分钟

用接口描述函数

普通函数

// 接口
interface Foo {
  (a: number, b: number): number;
}

//约束类型
const foo: Foo = function (a, b) {
  return a + b;
};

构造函数

//定义了一个类
class Person {
	constructor(public name: string) {}
	getName() {
		return this.name;
	}
}

// 定义了一个构造函数
interface Foo {
	new (name: string): Person;
}

定义一个构造函数,和定义普通函数的区别在于前面加了一个new关键词

我们知道,接口就是用来描述对象形状的,那么定义一个构造函数,就是要求类中必须有该类型的构造函数

但是这样的接口不能像普通接口一样被继承。一个不能被实现的接口,要他何用?(这是一个疑问句,不是一个肯定句 [偷笑] )

用接口描述元组

当我们把数组看成一个对象,这个问题就迎刃而解了。因为,描述对象类型的任务,接口还是很擅长的

我们想要定义这样一个元组

let tuple: [string, number] = [ 'zora', 18];

这是用接口的实现

//用接口描述元组
// 类型固定,位置固定,长度固定
interface Tuple {
	0: string;
	1: number;
	length: 2;
}

下面是实现结果

只有第一种的声明赋值是成功不报错的,其他两种声明赋值是报错的。

可见接口定义元组是没有问题的。

用接口描述类的实例属性和静态属性

这是用接口描述类的实例属性

//用接口描述类的实例属性
interface InstancePerson{
    name: string;
    getName: ()=>string;
    setName(name: string): void;
}

class Person implements InstancePerson{
    constructor(public name: string){};

    getName(){
        return this.name;
    }
    setName(name: string){
        this.name = name;
    }

    static laugh(){}
}

如果你在InstancePerson里面添加 laugh属性的约束,那么当Person类实现该接口时, TS就会要求 Person类去重新实现laugh的方法,并且会忽略已经存在的静态方法laugh

为什么会这样?

  1. Person类实例化且生成p对象之后,该p对象的类型就是Person类的类型,也等同于InStancePerson接口的类型
  2. 因为静态属性和实例对象无关,只与类有关(ES5中,静态属性就是构造函数的属性),所以任何一个类实现的接口,约束了类的类型。只能约束类的非静态属性,而不能约束静态属性
  3. 证明完毕

那我们想要去约束类的静态属性应该怎么做呢

既然想要去约束,就不能使用传统的implements的做法了

这里声明两个接口:一个描述类的实例化属性、另一个描述类的静态属性

// 描述类的实例化属性
interface InstancePerson{
    name: string;
    getName: ()=>string;
    setName(name: string): void;
    laugh(): void;
}

// 描述类的静态属性
interface StaticPerson{
    new (name: string): Person;
    laugh(): void;
}

Person类去实现InstancePerson接口,并实现它

class Person implements InstancePerson{
    constructor(public name: string){};

    getName(){
        return this.name;
    }
    setName(name: string){
        this.name = name;
    }
}

上面定义了一个StaticPerson接口,其中要求类要有laugh类的静态属性。而很明显上面定义的 Person不满足这个要求

那我们要让TS来提醒我们吧 : "Person类中缺少了静态方法laugh啊!!"

//声明一个方法
function createPerson(p: StaticPerson,name: string): Person{
    return new p(name);
}

//调用声明的方法
let p = createPerson(Person,'chen');

image.png

上面声明的方法中,有两个参数,第二个是Person实例化要用的name;第一个是用来实例化的类;

我们对传入的类有个StaticPerson的类型要求。

也就是要求类中,要有一个满足这样的new (name: string): Person;构造函数,和laugh(): void;方法。

关键点来了,不要走神。

我们要知道,参数一要求是类,而类就相当于构造函数本身,其中要求的laugh(): void;方法,不就相当于要求构造函数上面要有这个方法吗,而构造函数的方法就是静态方法呀,就是和实例化对象无关的方法呀

你看,这样不就约束了类的静态属性么?

总结:

  1. 用接口描述函数
  2. 用接口描述元组
  3. 用接口描述类的实例属性,和静态属性
  4. 这么精彩都不点个关注么,球球宁了