TypeScript 学习总结之 接口

412 阅读5分钟

TypeScript

接口 interface

在 TypeScript 学习总结之基础类型 那一章节中,我稍微学习了一下 接口 interface, 对它有了初步了解, 接下来总结的是 TS文档接口这一章节。

函数类型

以官方文档代码为例, 我分析了几种函数注解的方式:

方式一:

(最常见的)

interface SearchFunc {
  (source: string, subString: string): boolean;
}

let mySearch: SearchFunc;
mySearch = function (source: string, subString: string) {
  let result = source.search(subString);
  return result > -1;
}

方式二:

// 这种注解方式, 你会发现它同样把函数的实现方式也给实现了。 这样做不太好

interface SearchFunc {
  (source: string, subString: string): boolean;
}

// let mySearch: SearchFunc;
// mySearch = function (source: string, subString: string) {
//   let result = source.search(subString);
//   return result > -1;
// }

function mySearch(source: string, subString: string): boolean {
  let result = source.search(subString);
  return result > -1;
}

方式三:

// 通过 表达式的方式 你会发现 代码会显得特别长

interface SearchFunc {
  (source: string, subString: string): boolean;
}

let mySearch: (source: string, subString: string) => boolean = function (source: string, subString: string): boolean {
  let result = source.search(subString);
  return result > -1
}

方式四:

把方式三 给抽离出来看看

  1. 使用类型别名:
  2. 使用 接口 interface (这个和方式一 就一模一样了))

// 1.类型别名 方式

// 类型别名 方式
type SearchFunc = (source: string, subString: string) => boolean

let mySearch: SearchFunc = function (source: string, subString: string): boolean {
  let result = source.search(subString);
  return result > -1
}

// 2.接口 interface方式 (最常见的)

// 接口 interface
interface SearchFunc {
  (source: string, subString: string): boolean
}

let mySearch: SearchFunc = function (source: string, subString: string): boolean {
  let result = source.search(subString);
  return result > -1
}

可索引的类型 接口

可索引的类型的接口 指的就是 数组类型的接口

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

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

示例:

interface NumberArray {
  [index: number]: number
}

let obj: NumberArray = {
  0: 1,   // 其实这个索引值 0 1 2 都是字符串 虽然定义的是数字, 但终究会转换成string
  1: 2,
  2: 3
}

let arr: NumberArray = [1, 2, 3, 4]

因为当使用 number来索引时, JavaScript终究会将它转换成string 然后再去索引对象。

由此可知:在索引签名中, string是包含着number的

再举个例子:

class Animal {
  name: string;
}
class Dog extends Animal {
  breed: string;
}

// 错误:使用数值型的字符串索引,有时会得到完全不同的Animal!
// interface NotOkay {
//   [x: number]: Animal;
//   [x: string]: Dog;
// }

// success
interface NotOkay {
  [x: string]: Animal;//因为Animal是父类,只能是string
  [x: number]: Dog; // Dog继承了Animal 但索引又想和Animal一样,那么把它换成number即可
}

再看看 索引的返回值, 索引签名中 规定是什么类型就是什么类型,

因为 对象中key 一定是字符串,但value 不一定是

interface NumberDictionary {
  [index: string]: number;
  length: number;    // 可以,length是number类型
  // name: string       // 错误,`name`的类型与索引类型返回值的类型不匹配
  name:number  // OK
}

类 类型接口

对 类 的一部分行为进行抽象;

类实现所有接口中的属性和方法 && 对比 对象类: 抽象方法需要实现

与C#或Java里接口的基本作用一样,TypeScript也能够用它来明确的强制一个类去符合某种契约。

interface ClockInterface {
  currentTime: Date;		// 定义属性
  setTime(d: Date): void   // 定义方法
}
// implements  实现   专门用来实现接口
class Clock implements ClockInterface {
   currentTime = new Date();	// 实现实现
   setTime() {   // 实现方法

  }
  constructor(h: number, m: number) { }
}

类继承+类类型接口 示例:

interface Alarm {   //  警告器
  alert(): void
}

interface Light {   //  车灯
  color: string
  lightOn(): void
  lightOff(): void
}

class Door {

}
// 继承 Door (门) 这个类  然后实现   Alarm  接口
class securityDoor extends Door implements Alarm {
  alert() {
    console.log('咚咚咚');

  }
}

// car 要实现 这个俩个接口的方法和属性
class car implements Alarm, Light {
  color = 'red'
  alert() { }
  lightOn() { }
  lightOff() { }

}

类静态部分与实例部分的区别

类是具有两个类型的:静态部分的类型和实例的类型

而constructor 存在于类的静态部分, 所以不再检查的范围内

因此,类静态部分和实例部分需要单独分开来做

示例:

// 定于一个  闹钟接口
interface ClockInterface {
  currentTime: Date
  getTime(hour: number, mins: number): any
}
// 定于一个  闹钟构造函数接口
interface ClockConstructor {
  new(hour: number, mins: number): any
}

// Clock 去实现 闹钟接口ClockInterface
class Clock implements ClockInterface {
  currentTime = new Date()
  getTime() {

  }
}

// 定义一个构造函数 createClock 通过构造函数检查构造函数的方式 去 new 一个C
function createClock(C: ClockConstructor, hour: number, mins: number) {
  return new C(hour, mins)
}

// 实例化
let clock = createClock(Clock, 12, 12)

接口继承接口

因为 接口是对对象的形状进行描述; 所以接口可以继承接口,

和类一样,接口也可以相互继承。 这让我们能够从一个接口里复制成员到另一个接口里,可以更灵活地将接口分割到可重用的模块里。

interface Shape {
  color: string;
}

interface Square extends Shape {
  sideLength: number;
}

// 类型断言
// let square = <Square>{};
let square = {} as Square
square.color = "blue";
square.sideLength = 10;

混合类型

函数类型的interface ,添加属性的方式来实现 对象的interface

相当于 函数类型的interface + 对象类型的 interface

interface Counter {
  (start: number): string;   // 有点像构造函数
  interval: number;
  reset(): void;
}

function getCounter(): Counter {
  let counter = <Counter>function (start: number) { };  // 断言   可以理解为 给 counter 初始值
  counter.interval = 123;
  counter.reset = function () { };
  return counter;
}

let c = getCounter();
c(10);
c.reset();
c.interval = 5.0;

接口继承类

  1. 接口可以接触接口
  2. 接口可以继承类
  3. 类可以实现接口
//   定义 类
class Control {
  private state: any;
}

//  接口继承类
interface SelectableControl extends Control {
  select(): void;
}

//   类继承类然后实现接口
class Button extends Control implements SelectableControl {
  select() { }
}

//  类继承接口
class TextBox extends Control {
  select() { }
}

// 错误:“Image”类型缺少“state”属性。
// class Images implements SelectableControl {
//   select() { }
// }

最后,看了俩遍文档还是有点迷。。。。。 以后多练习练习