• 【TypeScript】语法详解 - 类型操作


    TypeScript中的类型操作

    🍤函数的参数类型

    函数是JavaScript非常重要的组成部分, TypeScript允许我们指定函数的参数和返回值的类型

    参数的类型注解

    声明函数时,可以在每个参数后添加类型注解,以声明函数接受的参数类型:

    function foo(name: string) {
      console.log("my name is" + name)
    }
    
    foo("chenyq")
    
    • 1
    • 2
    • 3
    • 4
    • 5

    为函数的参数添加类型注解后, 若再传入其他类型的参数, 或者不穿参数, 多传参数都会编译报错

    在这里插入图片描述


    🍤函数返回值类型

    我们也可以添加返回值的类型注解,这个注解出现在函数列表的后面

    function sum(num1: number, num2: number): number {
      return num1 + num2
    }
    
    sum(10, 20)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    和变量的类型注解一样,我们通常情况下不需要返回类型注解,因为TypeScript会根据 return 返回值推导出函数的返回类型

    某些第三方库处于方便使用者理解,会明确指定返回类型,但是这个看个人喜好;


    🍤匿名函数的参数

    通常情况下, 在定义一个函数时, 都会给参数加上类型注解的

    但是匿名函数与函数声明会有一些不同

    当一个函数出现在TypeScript可以确定该函数会被如何调用的地方时;

    该函数的参数会自动指定类型;

    const names = ["aaa", "bbb", "ccc"]
    names.forEach((item) => {
      console.log(item)
    })
    
    • 1
    • 2
    • 3
    • 4

    我们并没有指定item的类型注解(当然也可以添加类型注解),但是item是一个string类型

    这是因为TypeScript会根据forEach函数的类型以及数组的类型推断出item的类型;

    这个过程称之为上下文类型( contextual typing),因为函数执行的上下文可以帮助确定参数和返回值的类型;


    🍤接收对象的类型

    如果我们希望限定一个函数接受的参数是一个对象,这个时候要如何限定呢?

    我们可以使用对象类型;

    function printCoordinate(print: {x: number, y: number}) {
      console.log("x坐标:", print.x)
      console.log("y坐标:", print.y)
    }
    
    printCoordinate({x: 110, y: 310})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里我们使用了一个对象来作为类型

    在对象我们可以添加属性,并且告知TypeScript该属性需要是什么类型;

    属性之间可以使用,或者;来分割,最后一个分隔符是可选的;

    每个属性的类型部分也是可选的,如果不指定,那么就是any类型;


    🍤对象的可选类型

    对象类型也可以指定哪些属性是可选的,可以在属性的后面添加一个?

    例如上面代码中, 我们再添加对象的第三个属性z坐标, 而这个属性是可选的, 可以传可以不传

    function printCoordinate(print: {x: number, y: number, z?: number}) {
      console.log("x坐标:", print.x)
      console.log("y坐标:", print.y)
    
      if(print.z) {
        console.log("z坐标:", print.z)
      }
    }
    
    printCoordinate({x: 110, y: 310})
    // z属性可选的, 可以传可以不传
    printCoordinate({x: 110, y: 130, z: 190})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    可选类型还有很多内容, 我放在本篇文章的后面给大家讲解, 先在这里初步认识一下可选类型


    🍤联合类型的使用

    TypeScript的类型系统允许我们使用多种运算符,从现有类型中构建新类型

    我们来使用第一种组合类型的方法:联合类型( Union Type)

    联合类型是由两个或者多个其他类型组成的类型;

    表示可以是这些类型当中的任何一个值;

    联合类型中的每一个类型被称之为联合成员( union’s members);

    // 定义一个函数, 打印id, id可能为number, 可能为string
    function printID(id: number | string) {
      console.log(id)
    }
    
    printID("123")
    printID(456)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    传入给一个联合类型的值是非常简单的:只要保证是联合类型中的某一个类型的值即可

    但是我们拿到这个值之后,我们应该如何使用它呢?因为它可能是任何一种类型, 因此我们在使用联合类型是需要特别小心。

    比如我们拿到的值可能是string或者number,如果拿到number, 我们就不能对其调用string上的一些方法, 反之同理;

    那么我们怎么处理这样的问题呢?

    我们需要使用缩小( narrow)联合(后续我还会专门讲解缩小相关的功能);

    TypeScript可以根据我们缩小的代码结构,推断出更加具体的类型;

    • 例如当id为字符串时, 我们将其全部转换为大写; 当id为数字时就直接打印
    function printID(id: number | string) {
      if (typeof id === 'string') {
        console.log(id.toUpperCase())
      } else {
        console.log(id)
      }
    }
    
    printID("aaa")
    printID(123)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    🍤联合和可选关系

    例如我们有如下一个函数, 这个函数有一个参数, 且是可选类型的

    function foo(message?: string) {
      console.log(message)
    }
    
    foo() // 不写参数, 本质上相当于传入了一个undefined
    foo("abc")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    其实本质上,可选类型可以看做是 类型 undefined 的联合类型

    因此上面代码可以写成下面这样

    function foo(message: string|undefined) {
      console.log(message)
    }
    
    foo(undefined) // 此时若不想传入参数, 不能不传, 必须明确传入undefined
    foo("abc")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    🍤类型注解的别名

    在前面,我们通过在类型注解中编写对象类型和联合类型,但是当我们想要多次在其他地方使用时,就要编写多次。

    并且类型注解的对象类型和联合对象的代码有时候过于长了一些

    比如我们可以给对象类型或者联合类型起一个别名, 解决编写多次, 或代码过长的弊端

    定义类型注解别名通过type关键字

    // 为对象类型的类型注解取别名
    type Point = {
      // 可以用 "," 或 ";"分隔, 使用","可以省略
      x: number
      y: number
      z?: number
    }
    
    function printPoint(print: Point) {
      console.log("x坐标:", print.x)
      console.log("y坐标:", print.y)
    
      if(print.z) {
        console.log("z坐标:", print.z)
      }
    }
    
    function sumPoint(print: Point) {
      console.log(print.x + print.y)
    
      if(print.z) {
        console.log("z坐标:", print.z)
      }
    }
    
    printPoint({x: 110, y: 310})
    sumPoint({x: 110, y: 130, z: 190})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    // 为联合类型的类型注解添加别名
    type IDType = number | string
    
    function printID(id: IDType) {
      if (typeof id === 'string') {
        console.log(id.toUpperCase())
      } else {
        console.log(id)
      }
    }
    
    printID(123)
    printID("aaa")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 相关阅读:
    容灾恢复 | 记一次K8S集群中etcd数据快照的备份恢复实践
    数据趣事:历史最高温的是新疆吐鲁番?重庆45℃高温仅排全国第二
    P2PNet-Soy原理梳理
    线程重用导致ThreadLocal的数据混乱问题
    CPP emplace_bake 和 push_back 的相同和区别
    ShowMeBug入驻腾讯会议,开启专业级技术面试时代
    Python爬虫实战-小说网站爬虫开发
    二叉树的中序遍历
    家庭安全计划 挑战赛| 溺水预防
    【HNOI2012, 矿场搭建】割点
  • 原文地址:https://blog.csdn.net/m0_71485750/article/details/126324362