hackftz

bits change world

导航

深入理解TypeScript——文档篇之接口

Posted on 2020-10-01 16:03  hackftz  阅读(224)  评论(0编辑  收藏  举报

       接口是ts的核心之一,它的作用就是先约定好,再在定义的地方检查各种数据结构。

一、鸭子辩型法

       鸭式辨型:像鸭子一样走路、游泳和嘎嘎叫的鸟就是鸭子。如下:

interface Duck {
  walkLikeDuck(): any
  swim(): any
  gaga(): any
}

class Animal {
  walkLikeDuck() {
    console.log('look!, I walk like a duck.')
  }

  swim() {
    console.log('YES! I can swim very well.')
  }

  gaga() {
    console.log('gaga')
  }
}

let duck: Duck = new Animal()

console.log(duck);

二、初识

       理解为将函数、变量定义等等中的数据检查,抽离出来,成为接口。

三、可选属性(“option bags”模式)

       与普通的接口定义差不多,只是在可选属性名字定义的后面加一个?符号。

interface SquareConfig {
  color?: string;
  width?: number;
}

四、只读属性

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

interface Point {
    readonly x: number;
    readonly y: number;
}

       TypeScript具有ReadonlyArray<T>类型,数组创建后再也不能被修改。

ReadonlyArray赋值到一个普通数组也是不可以的。 但是你可以用类型断言重写。

a = ro as number[];

五、额外的属性检查

       对象字面量会被特殊对待而且会经过 额外属性检查,当将它们赋值给变量或作为参数传递的时候。 如果一个对象字面量存在任何“目标类型”不包含的属性时,你会得到一个错误。

interface SquareConfig {
    color?: string;
    width?: number;
  }

  function createSquare(config: SquareConfig): { color: string; area: number } {
      // ...
  }

  let mySquare = createSquare({ colour: "red", width: 100 });
  // 类型“{ colour: string; width: number; }”的参数不能赋给类型“SquareConfig”的参数。
  // 对象文字只能指定已知的属性,但“colour”中不存在类型“SquareConfig”。是否要写入 color?ts(2345)

       可以使用类型断言来绕开检查:

let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig);

索引签名:

       定义除已确定属性外的任意数量的其他额外属性。

interface SquareConfig {
    color?: string;
    width?: number;
    [propName: string]: any;
}

六、函数类型

       包含有参数列表和返回值类型的函数定义。

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

七、索引类型

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

interface StringArray {
  [index: number]: string;
}

let myArray: StringArray;
myArray = ["Bob", "Fred"];

let myStr: string = myArray[0];

       TypeScript支持两种索引签名:字符串和数字。 可以同时使用两种类型的索引,但是数字索引的返回值必须是字符串索引返回值类型的子类型。 这是因为当使用 number来索引时,JavaScript会将它转换成string然后再去索引对象。 也就是说用 100(一个number)去索引等同于使用"100"(一个string)去索引,因此两者需要保持一致。

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

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

八、类类型

       明确的强制一个类去符合某种约定。

interface ClockInterface {
    currentTime: Date;
}

class Clock implements ClockInterface {
    currentTime: Date;
    constructor(h: number, m: number) { }
}

九、继承接口

interface Shape {
    color: string;
}

interface Square extends Shape {
    sideLength: number;
}

let square = <Square>{};
square.color = "blue";
square.sideLength = 10;

       一个接口可以继承多个接口。

interface Shape {
    color: string;
}

interface PenStroke {
    penWidth: number;
}

interface Square extends Shape, PenStroke {
    sideLength: number;
}

十、混合类型

       一个对象可以同时做为函数和对象使用,并带有额外的属性。

十一、接口继承类

       当接口继承了一个类类型时,它会继承类的成员但不包括其实现。

       当创建了一个接口继承了一个拥有私有或受保护的成员的类时,这个接口类型只能被这个类或其子类所实现(implement)。

class Control {
    private state: any;
}

interface SelectableControl extends Control {
    select(): void;
}

class Button extends Control implements SelectableControl {
    select() { }
}

class TextBox extends Control {
    select() { }
}

// 类“Image”错误实现接口“SelectableControl”。
// 类型 "Image" 中缺少属性 "state",但类型 "SelectableControl" 中需要该属性。ts(2420)
class Image implements SelectableControl {
    select() { }
}

       这里指的是,接口SelectableControl继承类Control后的接口SelectableControl,类Image在实现时,必须要继承于Control类,也就是必须是它的子类才可以兼容。