TypeScript中接口的使用详解

一、接口的概述

TypeScript的核心原则是对值所具有的结构进行类型检查。

TypeScript里,接口的作用就是为这些类型命名,即声明对象类型。

二、接口的基本使用

// 声明一个接口
interface IPersonType {
    
    
  readonly name: string		// 定义只读属性
  age: number,				// 定义普通number类型的属性
  friend?: {
    
    				// 定义可选属性
    name: string
  }
}

// 定义一个person变量,变量的类型为IPersonType
const person: IPersonType = {
    
    
  name: "lucy",
  friend: {
    
    
    name: "jack"
  }
}

// 使用变量
console.log(info.friend?.name)
console.log(info.name)

关于接口的基本使用有一些注意点:

  • 给接口命名时,可以使用大写的I字母开头,代表这是个接口(interface

  • 接口的定义和类有些相似,都可以使用可选属性和只读属性

  • 声明对象类型更推荐使用接口的方式,而不是用type关键字

三、接口中定义索引类型

// 示例一:
// 定义一个 索引key为number类型, value为string类型的接口
interface IIndexLanguage {
    
    
  // index是形参, 名称自取
  [index: number]: string
}

// 定义一个上述接口类型的对象
const frontLanguage: IIndexLanguage = {
    
    
  0: "HTML",
  1: "CSS",
  2: "JavaScript",
  3: "Vue"
}

// 示例二:
interface ILanguageYear {
    
    
  [name: string]: number
}

const languageYear: ILanguageYear = {
    
    
  "C": 1972,
  "Java": 1995,
  "JavaScript": 1996,
  "TypeScript": 2014
}

使用这个方式,可以确保变量中的各个属性的键和值的类型都是一致的。

并且使用接口定义索引类型进行限制可以保证对象后续增加的属性和已存在的属性格式上保持一致。

四、使用接口约束函数

interface不仅定义对象中普通的属性和方法的,实也可以用来定义函数类型。

// type CalcFn = (n1: number, n2: number) => number

interface ICalcFn {
    
    					 	// 接口定义函数类型
  (n1: number, n2: number): number	 	//(函数参数): 函数返回值
}

const add: CalcFn = (num1, num2) => {
    
    	// 使用CalcFn接口约束函数变量的类型
  return num1 + num2
}

calc(20, 30)

一般来说,函数类型更推荐使用类型别名的方式来定义:

type CalcFun = (n1: number, n2: number) => number

五、接口继承

接口和类一样是可以进行继承的,也是使用extends关键字,并且接口是支持多继承的(而类是继承)。

扫描二维码关注公众号,回复: 15670241 查看本文章
// 游泳接口
interface ISwim {
    
    
  swimming: () => void
}

// 飞行接口
interface IFly {
    
    
  flying: () => void
}

// 动作接口,可以继承一个父接口,也可以继承多个
interface IAction extends ISwim, IFly {
    
    

}

// IAction接口继承自ISwim, IFly, 意味着使用IAction类型, 需要对swimming和flying方法都进行实现
const action: IAction = {
    
    
  swimming() {
    
    
	console.log("正在游泳。。。")
  },
  flying() {
    
    
    console.log("正在飞行。。。")
  }
}

七、接口中使用交叉类型

7.1 交叉类型概述

类型合并方式主要有两种:

  • 联合类型:表示多个类型中一个即可

    type ageType = number | string
    
  • 交叉类型:表示要同时满足多个类型的条件,使用&符号来表示

    type ageType = number & string
    

    但是其实没有同时满足是一个number又是一个string的值,所以ageType是一个never类型

7.2 交叉类型的使用

interface ISwim {
    
    
  swimming: () => void
}

interface IFly {
    
    
  flying: () => void
}

// 定义一个交叉类型
type actionType = ISwim & IFly
// 使用actionType类型, 需要对swimming和flying方法都进行实现
const action: actionType = {
    
    
  swimming() {
    
    
    console.log("swimming")
  },
  flying() {
    
    
    console.log("flying") 
  }
}

在开发中,通常是对对象类型进行交叉

八、接口的实现

接口定义后,不仅可以作为类型,也可以被类实现。

8.1 基础语法

interface IEat {
    
    
  eating: () => void
}

// 类实现接口
class Animal implements IEat{
    
    
  eating() {
    
    
    console.log("Fish Eating")
  }
}

实现接口使用implements关键字

实现了对应接口的类,一定要实现接口中未实现的抽象类

8.2 接口多实现

interface IEat {
    
    
  eating: () => void
}

interface ISwim {
    
    
  swimming: () => void
}

// 类实现接口
class Animal implements IEat, ISwim{
    
    
  eating() {
    
    
    console.log("Fish Eating")
  }
  swimming() {
    
    
    console.log("Fish Swmming")
  }
}

一个类可以同时实现多个接口,但是不可以继承多个父类

8.3 接口中的多态

如果被一个类实现,那么在之后需要传入接口的地方,都可以将这个类传入。

这就是面向接口开发;基于的是面向对象中多态的特性。

class Person implements ISwim {
    
    
  swimming() {
    
    
    console.log("Person Swimming")
  }
}

// 编写一些公共的API: 面向接口编程
function swimAction(swimable: ISwim) {
    
    
  swimable.swimming()
}

// 实现了接口的类对应的对象, 都是可以作为参数传入
swimAction(new Person())

九、interface和type的区别

interfacetype都可以用来定义对象类型,那么在开发中定义对象类型时,该如何选择?

  • 如果是定义非对象类型,推荐使用type

  • 如果是定义对象类型,那么他们是有区别的:

    • interface 可以重复的对某个接口来定义属性和方法 ,对于名称相同的接口, 会将属性进行合并
    • type定义的是别名,别名是不能重复的

猜你喜欢

转载自blog.csdn.net/qq_44749491/article/details/127525970
今日推荐