TypeScript学习笔记(五):接口

时间:2021-08-25 15:36:20

使用接口

在前面的笔记中我们知道可以使用Object Type来指定参数的属性,如下:

TypeScript学习笔记(五):接口
1 function printLabel(labelledObj: {label: string}) {
2   console.log(labelledObj.label);
3 }
4 
5 var myObj = {size: 10, label: "Size 10 Object"};
6 printLabel(myObj);
TypeScript学习笔记(五):接口

这种做法也可以通过接口实现:

TypeScript学习笔记(五):接口
 1 interface LabelledValue {
 2   label: string;
 3 }
 4 
 5 function printLabel(labelledObj: LabelledValue) {
 6   console.log(labelledObj.label);
 7 }
 8 
 9 var myObj = {size: 10, label: "Size 10 Object"};
10 printLabel(myObj);
TypeScript学习笔记(五):接口

这里很有意思的一点是,传递的参数可以不实现该接口,仅仅带有接口的属性即可。

可选属性

TypeScript的接口还支持可选属性,这在之前的参数中已经说过,如下:

TypeScript学习笔记(五):接口
 1 interface SquareConfig {
 2   color?: string;
 3   width?: number;
 4 }
 5 
 6 function createSquare(config: SquareConfig): {color: string; area: number} {
 7   var newSquare = {color: "white", area: 100};
 8   if (config.color) {
 9     newSquare.color = config.collor;  // Type-checker can catch the mistyped name here
10   }
11   if (config.width) {
12     newSquare.area = config.width * config.width;
13   }
14   return newSquare;
15 }
16 
17 var mySquare = createSquare({color: "black"});  
TypeScript学习笔记(五):接口

我们传递的类型可带有也可不带有可选的属性。

函数类型

这里在之前其实已经说到了,如果你对C#比较熟悉的话,可以将函数类型看做C#中的委托,如下:

TypeScript学习笔记(五):接口
 1 interface SearchFunc {
 2   (source: string, subString: string): boolean;
 3 }
 4 
 5 var mySearch: SearchFunc;
 6 mySearch = function(source: string, subString: string) {
 7   var result = source.search(subString);
 8   if (result == -1) {
 9     return false;
10   }
11   else {
12     return true;
13   }
14 }
TypeScript学习笔记(五):接口

即定义为SerrchFunc类型的函数只能被赋值为在接口中定义好的参数和返回值一致的函数。

数组类型

我们可以通过接口来指定一个存放指定类型的数组:

TypeScript学习笔记(五):接口
1 interface StringArray {
2   [index: number]: string;
3 }
4 
5 var myArray: StringArray;
6 myArray = ["Bob", "Fred"];
TypeScript学习笔记(五):接口

数组类型的写法是固定的,前面表示索引,返回值表示数组中可以存放的类型,当然其实TypeScript的数组是支持泛型的,所以使用泛型会更加方便一点。

Class类型

终于说到接口最核心的使用方法了,即通过接口来规范类的类型:

TypeScript学习笔记(五):接口
 1 interface ClockInterface {
 2     currentTime: Date;
 3     setTime(d: Date);
 4 }
 5 
 6 class Clock implements ClockInterface  {
 7     currentTime: Date;
 8     setTime(d: Date) {
 9         this.currentTime = d;
10     }
11     constructor(h: number, m: number) { }
12 }
TypeScript学习笔记(五):接口

实现接口使用implements关键字,同时一个类可以实现多个接口,实现了同一接口的类都可以赋值给该接口类型的变量,这里和Java、C#等语言用法一致。

规范构造函数

这也是TypeScript中比较独特的地方了,可以通过接口来指定构造函数的参数,我们先看下面的写法:

TypeScript学习笔记(五):接口
1 interface ClockInterface {
2     new (hour: number, minute: number);
3 }
4 
5 class Clock implements ClockInterface  {
6     currentTime: Date;
7     constructor(h: number, m: number) { }
8 }
TypeScript学习笔记(五):接口

这个写法会报错,这在TypeScript中是不允许的写法。

规范构造函数的接口不能使用implemnets实现,而是作为类型存在,如下:

TypeScript学习笔记(五):接口
 1 interface ClockStatic {
 2     new (hour: number, minute: number);
 3 }
 4 
 5 class Clock  {
 6     currentTime: Date;
 7     constructor(h: number, m: number) { }
 8 }
 9 
10 var cs: ClockStatic = Clock;
11 var newClock = new cs(7, 30);
TypeScript学习笔记(五):接口

这样的写法就能达到我们想要的效果了。

接口继承

接口之间可以继承,同时支持多重继承,如下:

TypeScript学习笔记(五):接口
 1 interface Shape {
 2     color: string;
 3 }
 4 
 5 interface PenStroke {
 6     penWidth: number;
 7 }
 8 
 9 interface Square extends Shape, PenStroke {
10     sideLength: number;
11 }
12 
13 var square = <Square>{};
14 square.color = "blue";
15 square.sideLength = 10;
16 square.penWidth = 5.0;
TypeScript学习笔记(五):接口

这里要注意一下,square并不是实现了该接口的类,所以不能使用new来实现,而是使用<Square>{}的写法来创建,这里要注意一下。

混合类型

我们可以指定一个对象的类型,如下:

TypeScript学习笔记(五):接口
 1 interface Counter {
 2     (start: number): string;
 3     interval: number;
 4     reset(): void;
 5 }
 6 
 7 var c: Counter;
 8 c(10);
 9 c.reset();
10 c.interval = 5.0;
TypeScript学习笔记(五):接口