《三》TypeScript 中函数的类型定义

TypeScript 允许指定函数的参数和返回值的类型。

  1. 函数声明的类型定义:function 函数名(形参: 形参类型, 形参: 形参类型, ...): 返回值类型 {}

    function sum(x: number, y: number): number {
        return x + y
    }
    sum(1, 2) // 正确
    sum(1, 2, 3) // 错误。输入多余的或者少于要求的参数,都是不被允许的
    
  2. 函数表达式的类型定义:const 函数名: (形参: 形参类型, 形参: 形参类型, ...) => 返回值类型 = function () {}

    对函数本身进行类型声明:(形参: 形参类型, 形参: 形参类型, ...) => 返回值类型
    对没有参数和没有返回值的函数本身进行类型声明:() => void

    // 不规范的写法。可以通过编译,但事实上只是对等号右侧的匿名函数进行了类型定义,而等号左边 sum 是赋值操作后进行类型推论而推断出来的,并没有对 sum 函数本身进行类型声明
    const sum = function (x: number, y: number): number {
        return x + y
    }
    
    // 规范的写法。在 TypeScript 的类型定义中,=> 用来表示函数的定义,左边是输入类型,需要用括号括起来,右边是输出类型。
    const sum: (x: number, y: number) => number = function (x: number, y: number): number {
        return x + y
    }
    
    // 规范的写法还可以进行一些省略。在函数引用中定义好了函数的参数类型和返回值类型,那么函数体可以省略,不需要再次指定类型
    const sum: (x: number, y: number) => number = function (x, y) {
        return x + y
    }
    
  3. 函数的调用签名(Call Signatures):函数除了作为函数本身可以被调用外,还可以作为对象有属性和方法。但是,函数声明的类型定义和函数表达式的类型定义并不支持声明属性和方法,此时可以使用函数的调用签名。

    
    // 函数的调用签名的写法:可以用 Type,也可以用 interface
    type sumType = {
      // 对函数作为对象的属性值和方法的类型定义
      name: string,
      // 对函数作为函数本身的类型定义。写法为 (参数列表): 返回值类型
      (x: number, y: number): number,
    }
    
    const sum: sumType = function (x: number, y: number): number {
      return x + y
    }
    sum.name = 'sumFunc'
    sum(1, 2)
    
  4. 函数的构造签名:函数除了可以直接调用外,还可以使用 new 操作符调用,当通过 new 操作符调用时,TypeScript 就会认为这个函数是一个构造函数,会产生一个实例对象。此时,可以使用函数的构造签名。

    对函数进行普通的函数类型定义,也可以使用 new 操作符来调用。但是,TypeScript 类型推断出来的实例对象的类型是 any。
    请添加图片描述

    class Person {}
    
    // 在调用签名前面加一个 new 关键词
    type PersonType = {
      new (): Person,
    }
    
    function factory(callback: PersonType) {
      const p = new callback()
      return p
    }
    factory(Person)
    
    // 或者:在函数表达式前面加上 new 操作符
    // function factory(callback: new () => void) {
    //   const p = new callback()
    //   return p
    // }
    

    请添加图片描述

函数可选参数的类型定义:

可以用 ? 表示可选的参数,可选参数必须放在最后面。

function buildName(firstName: string, lastName?: string) {
    if (lastName) {
        return firstName + ' ' + lastName
    } else {
        return firstName
    }
}
let tomcat = buildName('Tom', 'Cat') // 正确
let tom = buildName('Tom') // 正确

在 ES6 中,允许给函数的参数添加默认值,TypeScript 会将添加了默认值的参数识别为可选参数,但此时不受可选参数必须放在最后面的限制。

function buildName(firstName: string = 'Tom', lastName: string) {
    return firstName + ' ' + lastName
}
let tomcat = buildName('Tom', 'Cat') // 正确
let cat = buildName(undefined, 'Cat') // 正确

函数重载的类型定义:

重载就是根据参数,选择相同函数名而参数不同的函数。严格来说,JS 中其实是没有函数重载的概念的。

在 TypeScript 中,可以去编写不同的重载签名来表示函数可以以不同的方式进行调用。一般是编写两个或者两个以上的重载签名,再去编写一个通用的函数实现。

// 实现函数接收两个参数,返回相加后的值。只能同时是数字,返回数字;或者同时是字符串,返回字符串
// 1. 先编写函数的重载签名:是没有实现体的
function add(arg1:number, arg2: number): number
function add(arg1:string, arg2: string): string
// 2. 然后编写通用的函数实现:是有实现体的
function add(arg1, arg2) {
  return arg1 + arg2
}

// 3. 在调用函数的时候,会根据传入的参数类型来决定执行函数体时,执行哪一个函数的重载签名
add(10, 20) // 正确
add('Hello', 'World') // 正确
add(10, 'World) // 错误。调用的是函数的重载签名,通用函数不能被调用

函数中的 this 的类型:

this 的默认类型:

在没有对 TypeScript 进行特殊配置的情况下,函数中的 this 的默认类型是 any。

请添加图片描述

请添加图片描述

明确指定 this 的类型:

当在 tsconfig.json 配置文件中设置 compilerOptions 编译选项下的 noImplicitThis 为 true 时,表明不允许模糊的 this。此时,TypeScript 会根据上下文推断 this 的类型,如果能推断出具体的类型,不会报错;否则将会报错,此时就需要明确地指定 this 的类型。

请添加图片描述
请添加图片描述
需要将 this 作为函数的第一个参数来明确地指定类型。this 参数会在编译后会抹除。

function studying(this: {name: string}) {
  console.log(this) // 正确
}
studying.call({name: 'Lee'})

this 相关的内置工具:

TypeScript 提供了一些工具类型来辅助进行常见的类型转换,这些类型全局可用。

  1. ThisParameterType:用于获取一个函数类型中的 this 参数的类型。如果这个函数类型没有 this 参数的话,返回 unknown。

    function studying(this: {name: string}) {
      console.log(this)
    }
    
    // 获取 studying 函数的类型
    type studyingType = typeof studying
    
    // 获取 studyingType 类型中的 this 的类型
    type studyingThisType = ThisParameterType<studyingType>
    

    请添加图片描述

  2. OmitThisParameter:用于移除一个函数类型中的 this 参数的类型,返回当前的函数类型。

    function studying(this: {name: string}, ) {
      console.log(this)
    }
    
    // 获取 studying 函数的类型
    type studyingType = typeof studying
    
    // 获取移除了 this 参数类型的纯净的函数类型
    type pureStudyingType = OmitThisParameter<studyingType>
    

    请添加图片描述

  3. ThisType:用于绑定一个上下文的 this。

    type StateType = {
      name: string,
      age: 18,
    }
    
    type StoreType = {
      state: StateType,
      studying: () => void,
    }
    
    const store: StoreType = {
      state: {
        name: 'Lee',
        age: 18,
      },
      studying: function() {
        console.log(this.name) // 错误。此时 TypeScript 类型推断出的 this 是 store
      }
    }
    

    可以通过明确地指定 this 的类型来解决。但是,如果有很多地方都需要用到 this,就会很繁琐。

    const store: StoreType = {
      state: {
        name: 'Lee',
        age: 18,
      },
      studying: function(this: StateType) {
        console.log(this.name)
      }
    }
    
    store.studying.call(store.state)
    

    可以用 ThisType 来绑定一个上下文的 this。
    请添加图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值