接口的介绍

接口的作用:
在面向对象的编程中,接口是一种规范的定义,它定义了行为和动作的规范。在程序设计里面,接口起到一种限制和规范的作用。接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部状态数据,也不关心这些类里方法的实现细节,它只规定这批类里必须提供某些方法,提供这些方法的类就可以满足实际需要。
接口的另一个用途,对类的一部分行为进行抽象。

接口的定义

接口用 interface 定义。

举个简单的例子看如何声明一个接口:

  1. interface User {
  2. name: string;
  3. age?: number;
  4. }
  5. const getUserName = (user: User) => user.name;
  6. const ff = getUserName({ name: "ff", age: 18 });

接口的属性

可选属性

接口里的属性不全都是必需的,有些是只在某些条件下存在,或者根本不存在。
带有可选属性的接口与普通的接口定义差不多,只是在可选属性名字定义的后面加一个 ? 符号。
可选属性的好处之一是可以对可能存在的属性进行预定义,好处之二是可以捕获引用了不存在的属性时的错误。

只读属性

一些对象属性只能在对象刚刚创建的时候修改其值。可以在属性名前用 readonly 来指定只读属性。

readonlyconst 都是不允许改变值,那么该怎么区分这两个呢?
最简单判断该用 readonly 还是 const 的方法是看要把它作为变量使用还是作为一个属性。作为变量使用的话用 const ,若作为属性则使用 readonly

接口类型

属性接口

对传入对象进行约束

  1. interface User {
  2. name: string
  3. age?: number
  4. readonly isMale: boolean
  5. }
  6. const getUserName = (user: User) => user.name;

函数类型接口

对方法传入的参数以及返回值进行约束

  1. interface encrypt {
  2. (key: string, value: string): string;
  3. }
  4. var md5:encrypt = function(key: string, value: string): string {
  5. }

可索引接口

对数组/对象的约束。可索引类型具有一个索引签名,它描述了对象索引的类型,还有相应的索引返回值类型。

  1. interface UserArr {
  2. [index: number]: string;
  3. }
  4. var arr: UserArr = ['aaa', 'bbb']
  5. console.log(arr[0]);

上面的例子中。定义了 UserArr 接口,它具有索引签名。这个索引签名表示了当用 number 去索引 UserArr 时会得到 string 类型的返回值。

TypeScript 支持两种索引签名:字符串和数字。可以同时使用两种类型的索引,但是数字索引的返回值必须是字符串索引返回值类型的子类型。

类类型接口

对类的约束,和抽象类有点类似

  1. interface Animal {
  2. name: string;
  3. eat(str: string):void;
  4. }
  5. class Dog implements Animal {
  6. name: string;
  7. constructor(name: string) {
  8. this.name = name;
  9. }
  10. eat() {
  11. console.log(`${this.name} is eating.`);
  12. }
  13. }

接口描述了类的公共部分,而不是公共和私有两部分。它不会帮你检查类是否具有某些私有成员。
由于类是有两个类型的:静态部分的类型和实例的类型。而当一个类实现了一个接口时,只对其实例部分进行类型检查,所以当你用构造器签名去定义一个接口并试图定义一个类去实现这个接口时会得到一个错误。

  1. interface ClockConstructor {
  2. new (hour: number, minute: number);
  3. }
  4. class Clock implements ClockConstructor {
  5. currentTime: Date;
  6. constructor(h: number, m: number) { }
  7. }

接口扩展

接口可以继承接口

  1. interface Animal {
  2. eat(): void;
  3. }
  4. interface Person extends Animal {
  5. work(): void;
  6. }
  7. class Web implements Person {
  8. name: string;
  9. constructor(name: string) {
  10. this.name = name;
  11. }
  12. eat() {
  13. console.log(this.name + 'is eating');
  14. }
  15. work() {
  16. console.log(this.name + 'is working');
  17. }
  18. }

接口继承类

当接口继承了一个类类型时,它会继承类的成员但不包括其实现。就好像接口声明了所有类中存在的成员,但并没有提供具体实现一样。接口同样会继承到类的 private 和 protected 成员。这意味着当你创建了一个接口继承了一个拥有私有或受保护的成员的类时,这个接口类型只能被这个类或其子类所实现。

  1. class Control {
  2. private state: any;
  3. }
  4. interface SelectableControl extends Control {
  5. select(): void;
  6. }
  7. class Button extends Control implements SelectableControl {
  8. select() { }
  9. }
  10. class TextBox extends Control {
  11. select() { }
  12. }
  13. // 错误:“Image”类型缺少“state”属性。
  14. class Image implements SelectableControl {
  15. select() { }
  16. }
  17. class Location {
  18. }