用接口描述函数

普通函数

  1. // 接口
  2. interface Foo {
  3. (a: number, b: number): number;
  4. }
  5. //约束类型
  6. const foo: Foo = function (a, b) {
  7. return a + b;
  8. };

构造函数

  1. //定义了一个类
  2. class Person {
  3. constructor(public name: string) {}
  4. getName() {
  5. return this.name;
  6. }
  7. }
  8. // 定义了一个构造函数
  9. interface Foo {
  10. new (name: string): Person;
  11. }

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

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

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

用接口描述元组

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

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

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

这是用接口的实现

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

下面是实现结果

image.png

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

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

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

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

  1. //用接口描述类的实例属性
  2. interface InstancePerson{
  3. name: string;
  4. getName: ()=>string;
  5. setName(name: string): void;
  6. }
  7. class Person implements InstancePerson{
  8. constructor(public name: string){};
  9. getName(){
  10. return this.name;
  11. }
  12. setName(name: string){
  13. this.name = name;
  14. }
  15. static laugh(){}
  16. }

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

image.png
image.png

为什么会这样?

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

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

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

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

  1. // 描述类的实例化属性
  2. interface InstancePerson{
  3. name: string;
  4. getName: ()=>string;
  5. setName(name: string): void;
  6. laugh(): void;
  7. }
  8. // 描述类的静态属性
  9. interface StaticPerson{
  10. new (name: string): Person;
  11. laugh(): void;
  12. }

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

  1. class Person implements InstancePerson{
  2. constructor(public name: string){};
  3. getName(){
  4. return this.name;
  5. }
  6. setName(name: string){
  7. this.name = name;
  8. }
  9. }

上面定义了一个StaticPerson接口,其中要求类要有laugh类的静态属性。而很明显上面定义的
Person不满足这个要求 那我们要让TS来提醒我们: “Person类中缺少了静态方法laugh啊!!”

  1. //声明一个方法
  2. function createPerson(p: StaticPerson,name: string): Person{
  3. return new p(name);
  4. }
  5. //调用声明的方法
  6. let p = createPerson(Person,'chen');

image.png

声明的方法中,有两个参数,第二个是Person实例化要用的name;第一个是用来实例化的类; 这里我们对传入的类有个StaticPerson的类型要求。

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

关键点来了,不要走神。

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

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

总结:

  1. 用接口描述函数
  2. 用接口描述元组
  3. 用接口描述类的实例属性,和静态属性