• 【TypeScript】中接口的详细介绍


    TypeScript接口的使用

    🧊接口定义对象类型

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

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

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

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

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

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

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

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

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

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

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

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

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


    🧊接口定义索引类型

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

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

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

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

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

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

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

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

    🧊接口定义函数类型

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

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

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

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

    🧊接口的继承

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

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

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

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

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

    🧊交叉类型

    前面我们学习了联合类型

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

    type IDType = number | string
    
    • 1

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

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

    交叉类型使用 & 符号;

    我们来看下面的交叉类型

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

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

    type IDType = number & string
    
    • 1

    交叉类型的应用

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

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

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

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

    方式二: 交叉类型来结合


    🧊接口的实现

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

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

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

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

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

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

    这就是面向接口开发;

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

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

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

    🧊接口和type的区别

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

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

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

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

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

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

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

    在这里插入图片描述

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

  • 相关阅读:
    云服务器相比较物理服务器的好处有哪些?
    29、分块式内存管理[malloc、free]
    行业追踪,2023-10-09
    ElasticSearch使用入门及拼音搜索介绍
    基于Micropython的桌面信息小摆件
    SpringBoot SpringBoot 原理篇 3 核心原理 3.4 启动流程【3】
    短视频矩阵系统源码saas开发技术搭建代部署
    多变量时间序列生成模型GAN介绍与实现
    06-分布式中间件-Mycat-ShardingJDBC
    C++ Map empty()实例讲解
  • 原文地址:https://blog.csdn.net/m0_71485750/article/details/126338589