【TypeScript】中接口的详细介绍

谁借莪1个温暖的怀抱¢ 2024-04-27 15:54 180阅读 0赞

文章目录

    • TypeScript接口的使用
      • ?接口定义对象类型
      • ?接口定义索引类型
      • ?接口定义函数类型
      • ?接口的继承
      • ?交叉类型
      • ?接口的实现
      • ?接口和type的区别

TypeScript接口的使用

?接口定义对象类型

在前面我们通过type可以用来声明一个对象类型

通过类型别名(type), 声明一个对象类型

  1. type InfoType = {
  2. name: string
  3. age: number
  4. }
  5. const info: InfoType = {
  6. name: "chnyq",
  7. age: 18
  8. }

对象类型的另外一种声明方式, 就是通过接口来声明

通过接口, 声明一个对象类型

  1. interface InfoType {
  2. name: string
  3. age: number
  4. }
  5. const info: InfoType = {
  6. name: "chnyq",
  7. age: 18
  8. }

使用接口定义时, 有一个规范, 接口名前面加上一个”I”, 这个是规范, 遵不遵守看个人意愿

  1. // 接口名前面加上一个大写的I
  2. interface IInfoType {
  3. name: string
  4. age: number
  5. }
  6. const info: IInfoType = {
  7. name: "chnyq",
  8. age: 18
  9. }

接口定义对象类型时, 同样可以定义可选类型, 使用方式和之前是一样的

  1. interface InfoType {
  2. name: string
  3. // 添加可选类型
  4. age?: number
  5. }
  6. const info: InfoType = {
  7. name: "chnyq",
  8. // age: 18
  9. }

接口也可以定义只读属性, readonly

  1. interface InfoType {
  2. // 定义只读属性
  3. readonly name: string
  4. age: number
  5. }
  6. const info: InfoType = {
  7. name: "chnyq",
  8. age: 18
  9. }

两种定义对象类型的方式在使用上的区别,我会在下面讲到, 接下来我们继续学习一下接口的其他特性


?接口定义索引类型

前面我们使用interface来定义对象类型,这个时候其中的属性名、类型、方法都是确定的,但是有时候我们会遇 到类似下面的对象

例如我想使用一个对象(正常用数组, 在这里我偏要用对象o.0), 来存放我们前端需要学习的部分技术

  1. const frontLanguage = {
  2. 0: "HTML",
  3. 1: "CSS",
  4. 2: "JavaScript",
  5. 3: "Vue",
  6. 4: "TypeScript"
  7. }

此时我们对象中key是number类型, value是string类型

如果我们想要限制对象后续增加的属性, key也是number类型, value也是string类型的话, 我们可以使用接口定义索引类型进行限制

  1. interface IndexLanguage {
  2. // 表示索引key为number类型, value为string类型
  3. // index相当于是形参, 可以自己取名的
  4. [index: number]: string
  5. }
  6. const frontLanguage: IndexLanguage = {
  7. 0: "HTML",
  8. 1: "CSS",
  9. 2: "JavaScript",
  10. 3: "Vue",
  11. 4: "TypeScript",
  12. // 再添加其他类型的话就会报错
  13. // "abc": "12"
  14. }

当然, key不是只能为number类型, value也不是只能为string类型, 这个都是可以自定义的

  1. interface LanguageBirth {
  2. [name: string]: number
  3. }
  4. const language: LanguageBirth = {
  5. "Java": 1995,
  6. "JavaScript": 1996,
  7. "C": 1972
  8. }

?接口定义函数类型

前面我们都是通过interface来定义对象中普通的属性和方法的,实际上它也可以用来定义函数类型

  1. // 接口定义函数类型
  2. interface CalcFun {
  3. // 固定的语法
  4. (n1: number, n2: number): number
  5. }
  6. const add: CalcFun = (n1: number, n2: number) => {
  7. return n1 + n2
  8. }
  9. const mul: CalcFun = (num1: number, num2: number) => {
  10. return num1 * num2
  11. }
  12. // 测试
  13. console.log(add(10, 20)) // 30
  14. console.log(mul(10, 20)) // 200

当然,除非特别的情况,函数类型还是推荐大家使用类型别名的方式来定义

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

?接口的继承

接口和类一样是可以进行继承的,也是使用extends关键字

  1. interface Swim {
  2. swimming: () => void
  3. }
  4. // Action接口继承自Swim接口
  5. interface Action extends Swim {
  6. }
  7. // 由于Action继承自Swim, 意味着使用Action类型, 同样需要对swimming方法实现
  8. const action: Action = {
  9. swimming() {
  10. console.log("swimming")
  11. }
  12. }

并且我们会发现,接口是支持多继承的(类不支持多继承)

例如下面代码, 我定义两个接口: Swim和Fly, 我们使用一个接口继承自这两个接口

  1. interface Swim {
  2. swimming: () => void
  3. }
  4. interface Fly {
  5. flying: () => void
  6. }
  7. // Action接口继承自Swim和Fly接口
  8. interface Action extends Swim, Fly {
  9. }
  10. // 意味着使用Action类型, 需要对swimming和flying方法都进行实现
  11. const action: Action = {
  12. swimming() {
  13. console.log("swimming")
  14. },
  15. flying() {
  16. console.log("flying")
  17. }
  18. }

?交叉类型

前面我们学习了联合类型

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

  1. type IDType = number | string

还有另外一种类型合并方式,就是交叉类型( Intersection Types)

交叉类似表示需要满足多个类型的条件;

交叉类型使用 & 符号;

我们来看下面的交叉类型

表达的含义是number和string要同时满足;

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

  1. type IDType = number & string

交叉类型的应用

在开发中,我们使用交叉类型时,通常是对对象类型进行交叉的

  1. interface Swim {
  2. swimming: () => void
  3. }
  4. interface Fly {
  5. flying: () => void
  6. }
  7. // 定义一个交叉类型
  8. type myType = Swim & Fly
  9. // 使用交叉类型, 需要同时实现Swim和Fly类型的方法
  10. const obj: myType = {
  11. swimming() {
  12. console.log("swimming")
  13. },
  14. flying() {
  15. console.log("flying")
  16. }
  17. }

也就是说, 我们组合接口就有了两种方式

方式一: 使用接口的多继承

方式二: 交叉类型来结合


?接口的实现

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

实现接口是使用的implements关键字

  1. interface Swim {
  2. swimming: () => void
  3. }
  4. // 类实现接口
  5. class Action implements Swim {
  6. swimming() {
  7. console.log("swimming")
  8. }
  9. }

类实现接口也是可以进行多实现的

  1. interface Swim {
  2. swimming: () => void
  3. }
  4. interface Fly {
  5. flying: () => void
  6. }
  7. // 类多实现接口
  8. class Action implements Swim, Fly {
  9. swimming() {
  10. console.log("swimming")
  11. }
  12. flying() {
  13. console.log("flying")
  14. }
  15. }

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

这就是面向接口开发;

  1. // 函数要求传入一个接口
  2. function swim(swimmer: Swim) {
  3. swimmer.swimming()
  4. }
  5. const act = new Action()
  6. // 由于Action类实现了接口, 所以类可以直接传入
  7. swim(act)

一个类, 是可以同时继承父类, 又实现或者多实现接口

  1. interface Swim {
  2. swimming: () => void
  3. }
  4. interface Fly {
  5. flying: () => void
  6. }
  7. class Animal {
  8. }
  9. // 继承父类的同时, 又实现接口
  10. class Action extends Animal implements Swim, Fly {
  11. swimming() {
  12. console.log("swimming")
  13. }
  14. flying() {
  15. console.log("flying")
  16. }
  17. }

?接口和type的区别

我们会发现interface和type都可以用来定义对象类型,那么在开发中定义对象类型时,到底选择哪一个呢?

如果是定义非对象类型,通常推荐使用type,比如Direction、 Alignment、一些Function;

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

  • interface可以重复的对某个接口来定义属性和方法;

对于名称相同的接口, 会将属性进行合并

  1. interface Foo {
  2. name: string
  3. }
  4. interface Foo {
  5. age: number
  6. }
  7. // name和age都需要定义
  8. const foo: Foo = {
  9. name: "chenyq",
  10. age: 18
  11. }

而type定义的是别名,别名是不能重复的;

在这里插入图片描述

对于定义对象类型, 建议使用interface(官方给的建议也是interface), 也可以根据自己的爱好选择

发表评论

表情:
评论列表 (有 0 条评论,180人围观)

还没有评论,来说两句吧...

相关阅读

    相关 TypeScript接口

    TypeScript 的核心原则之一是对值所具有的结构进行类型检查。我们使用接口(Interfaces)来定义对象的类型。`接口是对象的状态(属性)和行为(方法)的抽象(描述)

    相关 TypeScript 接口介绍

    一、介绍 TypeScript的核心原则之一是对值所具有的结构进行类型检查。接口的作用就是这些类型名称和为你的代码或第三方代码定义契约。 和C\中一样,接口定义规则,不定义