• 【TypeScript】中的函数详解


    TypeScript函数详解

    🍧函数类型表达式

    在JavaScript开发中,函数是重要的组成部分,并且函数可以作为一等公民(可以作为参数,也可以作为返回值进行传递)

    那么在使用函数的过程中,函数是否也可以有自己的类型呢?

    我们可以编写函数类型的表达式( Function Type Expressions),来表示函数类型

    // 表示一个接收两个number类型的参数, 且返回值也是number类型的函数类型
    type CalcFun = (num1: number, num2: number) => number
    
    function calc(fn: CalcFun, n1: number, n2: number) {
      return fn(n1, n2)
    }
    
    // 定义两数相加的函数
    function sum(num1: number, num2: number) {
      return num1 + num2
    }
    //  定义两数相乘的函数
    function mul(num1: number, num2: number) {
      return num1 * num2
    }
    
    // 测试
    console.log(calc(sum, 10, 30))
    console.log(calc(mul, 20, 30))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在上面的语法中 (num1: number, num2: number) => number,代表的就是一个函数类型

    接收两个参数的函数: num1和num2,并且都是number类型;

    并且这个函数是有返回值的, 返回值类型也是number;

    注意: 在某些语言中,可能参数名称num1和num2是可以省略,但是在TypeScript是不可以的


    🍧参数的可选类型

    参数的可选类型在前面我有讲过, 这里再对函数参数的可选类型进行一些补充

    参数的可选类型, 可以指定某个参数是可选的

    如下: 参数x是必传的, 而y是可选的, 也就是说可传可不传

    function foo(x: number, y?: number) {
      console.log(x, y)
    }
    
    // 测试
    foo(10)
    foo(50, 20)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    补充一:

    这个时候这个参数y依然是有类型的,它是 number | undefined 的联合类型

    当参数y没有传参数时, 本质上就相当于将 y = undefined 传入函数中

    补充二:

    可选类型需要写在必传参数的后面, 写在前面编译阶段报错

    // 错误演示
    function foo(y?: number, x: number) {
      console.log(x, y)
    }
    
    • 1
    • 2
    • 3
    • 4

    🍧函数的剩余参数

    从ES6开始, JavaScript也支持剩余参数,剩余参数语法允许我们将一个不定数量的参数放到一个数组中

    例如下面例子中, 使用剩余参数编写一个函数, 可以对任意数量的数字相加

    function sum(...nums: number[]) {
      let result = 0
      nums.forEach(item => {
        result += item
      })
    
      return result
    }
    
    // 测试
    console.log(sum(10, 20, 30))
    console.log(sum(10, 20, 30, 40, 50, 60))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    注意: 如果函数还有其他参数, 剩余参数要放到参数列表的最后面


    🍧this的类型使用

    this是JavaScript中一个比较难以理解和把握的知识点

    我在JS高级中也有一篇文章专门讲解this: https://blog.csdn.net/m0_71485750/article/details/125174357;

    因为this在不同的情况下会绑定不同的值,所以对于它的类型就更难把握了;

    那么,TypeScript是如何处理this呢?我们先来看一个例子

    const info = {
      name: "chenyq",
      running() {
        console.log(this.name + " is running~")
      }
    }
    
    info.running() // chenyq is running~
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    上面的代码是可以正常运行的,也就是TypeScript在编译时,认为我们的this是可以正确去使用的

    TypeScript认为函数 sayHello 是通过外部对象 info调用的(隐式绑定),所以在使用时,就会把this当做该info对象。

    但是对于某些情况来说,TypeScript并不知道this到底是什么, 是推导不出来this指向谁的

    function running() {
      console.log(this.name + " is running~")
    }
    
    const info = {
      name: "chenyq",
      running
    }
    
    info.running()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    上面这段代码运行会报错的

    这里我们再次强调一下, TypeScript进行类型检测的目的是让我们的代码更加的安全;

    所以这里对于running的调用来说,我们虽然将其放到了info中,通过info去调用, this应该依然是指向info对象的

    但是对于TypeScript编译器来说,这个代码是非常不安全的,因为我们也有可能直接调用函数,或者通过别的对象来调用函数;

    解决方法,通常TypeScript会要求我们明确的指定this的类型

    // 明确指定this的类型
    function running(this: { name: string }) {
      console.log(this.name + " is running~")
    }
    
    const info = {
      name: "chenyq",
      running
    }
    
    info.running()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    明确指定了this的类型后, 就不能独立调用函数, 独立调用会编译报错

    在这里插入图片描述

    可以通过call, apply, bind调用 (显式绑定), 但是同样也需要指定绑定对象, 且该对象还需要有name属性

    function running(this: { name: string }) {
      console.log(this.name + " is running~")
    }
    
    const info = {
      name: "chenyq",
      running
    }
    
    running.call({name: "kaisa"}) // kaisa is running~
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    🍧函数的重载介绍

    在TypeScript中,如果我们编写了一个add函数,希望可以对字符串和数字类型进行相加,应该如何编写呢?

    type Sum = number|string
    function sum(n1: Sum, n2: Sum) {
      return n1 + n2
    }
    
    • 1
    • 2
    • 3
    • 4

    我们可能会像上面这样来编写,但是其实是错误的, 编译阶段就会报错

    在这里插入图片描述

    那么这个代码我们可以使用函数的重载编写

    函数的重载: 函数名称相同, 但是参数不同的几个函数, 就是函数重载

    参数不同: 参数的个数不同, 或者参数的类型不同, 都称为参数不同

    在TypeScript中,我们可以去编写不同的重载签名( overload signatures)来表示函数可以以不同的方式进行调用;

    一般是编写两个或者以上的重载签名,再去编写一个通用的函数, 也就是一个具体的实现的函数;

    // 重载签名, 需要声明返回值类型
    function sum(n1: number, n2: number): number;
    function sum (n1: string, n2: string): string;
    
    // 重载函数实现
    function sum(n1: any, n2: any) {
      return n1 + n2
    }
    
    // 测试
    console.log(sum(123, 10)) // 133
    console.log(sum("aa", "bb")) // aabb
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    注意在函数的重载中, 实现函数是不能直接被调用的

    例如下面的例子, 调用sum函数会在重载签名中从上到下一次匹配, 都没有匹配到, 就会报错, 并不会执行重载函数的实现函数

    在这里插入图片描述

  • 相关阅读:
    uniapp的两个跳转方式
    Vuex插件的安装与使用原理
    【Linux】linux中,你不得不爱的命令集(下)
    VueX/Pinia的优缺点
    SpringBoot解决跨域问题的六种方式
    【每日一题】移除链表元素(C语言)
    彻底掌握Python中 * 号
    2023-09-17力扣每日一题
    Flume部署实验
    Windows + Msys 下编译 TensorFlow 2.14
  • 原文地址:https://blog.csdn.net/m0_71485750/article/details/126331347