【TypeScript】接口

一、介绍

  • TypeScript的核心原则之一是对值所具有的结构进行类型检查
  • 接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约
  • 接口是一种规范的定义
  • 关键词:interface
  • 类型:
    • 属性类型接口
    • 函数类型接口
    • 可索引接口
    • 类类型接口

二、接口类型

1、属性类型接口

1.1 定义接口

示例:

interface FullName {
    firstName: string;
    secondName: string;
}
function printName(name: FullName) {
    console.log(name.firstName + '--' + name.secondName);
}

let obj = { // 编译器只会检查那些必需的属性是否存在,并且其类型是否匹配
    firstName: 'xiao',
    secondName: 'ming',
    age: 12,
}
printName(obj)

1.2 可选属性

在可选属性名字定义的后面加一个?符号

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

function createSquare(config: SquareConfig): {color: string; area: number} {
  let newSquare = {color: "white", area: 100};
  if (config.color) {
    newSquare.color = config.color;
  }
  if (config.width) {
    newSquare.area = config.width * config.width;
  }
  return newSquare;
}

let mySquare = createSquare({color: "black"});

原生js封装ajax:

interface Config {
    type: string;
    url: string;
    data?: string;
    dataType: string;
}
function ajax(config: Config) {
    let xhr = new XMLHttpRequest();
    xhr.open(config.type, config.url, true);
    xhr.send(config.data);
    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4 && xhr.status == 200) {
            console.log('成功!');
            if (config.dataType == 'json') {
                console.log(JSON.parse(xhr.responseText));
            } else {
                console.log(xhr.responseText);
            }
        }
    }
}

ajax({
    type: 'get',
    data: 'name=zhangsan',
    url: 'http://a.itying.com/api/productlist',
    dataType: 'json',
})

1.3 只读属性

属性名前用 readonly来指定只读属性

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

let p1: Point = { x: 10, y: 20 };
p1.x = 5; // error!

2、函数类型接口

它就像是一个只有参数列表和返回值类型的函数定义。参数列表里的每个参数都需要名字和类型

2.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;
}

对于函数类型的类型检查来说,函数的参数名不需要与接口里定义的名字相匹配。重写上面的代码,函数的参数会逐个进行检查,要求对应位置上的参数类型是兼容的

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

3、可索引类型

可索引类型具有一个 索引签名,它描述了对象索引的类型,还有相应的索引返回值类型
TypeScript支持两种索引签名:字符串和数字

3.1 字符串类型索引签名

定义:

interface StringDictionary {
  [index: string]: string;
}

使用:

const myDict: StringDictionary = {
  name: 'John',
  greeting: 'Hello'
}

3.2 数字类型索引签名

定义:

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

使用:

const myArray: NumberDictionary = {
  10: 'ten',
  20: 'twenty'
};

3.3 同时使用两种类型的索引

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

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

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

3.4 索引签名设置只读

最后,你可以将索引签名设置为只读,这样就防止了给索引赋值

interface ReadonlyStringArray {
    readonly [index: number]: string;
}
let myArray: ReadonlyStringArray = ["Alice", "Bob"];
myArray[2] = "Mallory"; // error! 因为索引签名是只读的

4、类类型接口

对类的约束

4.1 实现接口

关键字: implements

// 定义类接口
interface ClockInterface {
    currentTime: Date; // 属性
    setTime(d: Date): void; // 方法
}

// 实现 ClockInterface 接口
class Clock implements ClockInterface {
    currentTime: Date;
    constructor() {
        this.currentTime = new Date();
    }

    setTime(d: Date) {
        this.currentTime = d;
    }
}

4.2 约束构造函数和静态属

使用 implements 只能约束类实例上的属性和方法,要约束构造函数和静态属性,需要这么写

interface CircleStatic {
    new(radius: number): void;
    pi: number;
}
 
const Circle: CircleStatic = class Circle {
    radius: number;
    static pi: 3.14; // 未定义静态属性 pi,会报错
    constructor(radius: number) { // 如果constructor 入参类型(比如写成string)不对,会报错:
       this.radius = radius;
   }
}

三、接口的扩展

1. 继承接口

和类一样,接口也可以相互继承,
关键字 extends

interface Shape {
    color: string;
}
interface Square extends Shape {
    length: number;
}

let square = <Square>{};
square.color = 'blue';
square.length = 10;

一个接口可以继承多个接口,创建出多个接口的合成接口

interface Shape {
    color: string;
}
interface PenStroke {
    width: number;
}
interface Square extends Shape, PenStroke {
    length: number;
}

let square = <Square>{};
square.color = 'blue';
square.length = 10;
square.width = 20;

2. 混合类型

一个对象可以同时具有上面提到的多种类型。

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

interface Counter {
    (start: number): string;
    interval: number;
    reset(): void;
}

function getCounter(): Counter {
    let counter = <Counter>function (start: number) { };
    counter.interval = 123;
    counter.reset = function () { };
    return counter;
}

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

3 接口继承类

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

class Control {
    private state: any;
}

// SelectableControl包含了Control的所有成员,包括私有成员state
interface SelectableControl extends Control {
    select(): void;
}

class Button extends Control implements SelectableControl {
    select() {}
}
class TextBox extends Control {
    select() {};
}
// Button和TextBox类是SelectableControl的子类(因为它们都继承自Control并有select方法)

// 错误:“Image”类型缺少“state”属性。Image并不是SelectableControl的子类
class Image1 implements SelectableControl {
    select() {};
}
  • 19
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值