Typescript 函数的类型 (七)

函数的类型

函数声明

在 javascript 中有两种常见的定义函数方法—函数声明和函数表达式

//函数声明

function sum(x, y) {
  return x + y
}

//函数表达式

let mysum = function (x, y) {
  return x + y
}

一个函数有输入和输出,要在 Typescript 中对其约束,需要把输入输出都考虑,其中函数声明的类型定义简单

function sum(x: number, y: number): number {
  return x + y
}

注意输入多余的(或者少于要求的)参数,是不被允许的

function sum(x: number, y: number): number {
  return x + y
}

sum(1, 2, 3)

//直接错误
  • 第二种错误
function sum(x: number, y: number) {
  return x + y
}

sum(1)

函数表达式

  • 如果我们现在要写一个函数表达式,可能会写成这样
let mySum = function (x: number, y: number): number {
  return x + y
}
  • 而真要是写函数自定义
let mySum: (x: number, y: number) => number = function (
  x: number,
  y: number
): number {
  return x + y
}

注意不要混淆了 Typescript 中的=>和 ES6 中的=>

在 Typescript 的类型定义中, =>用来表示函数的定义,左边是输入类型,需要括号括起来。右边是输出类型

在 ES6 中, =>表示箭头函数

接口也可以定义函数

  • 我们用接口的方式定义一个函数
interface SearchFunc {
  (source: string, subString: string): boolean;
}

let mySearch: SearchFunc

mySearch = function (source: string, subString: string) {
  return source.search(subString) !== -1
}

可选参数

前面提到:输入多余的(或者少于要求的)参数,是不被允许的.那么怎么定义可选的参数?

与接口类似,我们用?来表示可选的参数:

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

特别注意的就是 可选参数必须接在必修参数后面,换句话说,可选参数后面不允许再出现必修参数了

function buildName(firstName?: string, lastName: string) {
  if (lastName) {
    return firstName + '' + lastName
  } else {
    return firstName
  }
}

let tomcat = buildName('Tom', 'Cat')

let tom = buildName(undefined, 'Tom')

// index.ts(1,40): error TS1016: A required parameter cannot follow an optional parameter.

参数默认值

在 ES6 中,我们允许给函数的参数添加默认值,Typescript 会将添加了默认值的参数识别为可选参数

function buildName(firstName: string, lastName: string = 'Cat') {
  return firstName + '' + lastName
}

let tomcat = buildName('Tom', 'Cat')
let tom = buildName('Tom')
  • 此时就不受 可选参数必须接在必须参数后面的限制了
function buildName(firstName: string = 'Tom', lastName: string) {
  return firstName + ' ' + lastName
}
let tomcat = buildName('Tom', 'Cat')
let cat = buildName(undefined, 'Cat')

剩余参数

ES6 中 可以使用 …rest 的方式获取函数中的剩余参数(rest 参数)

function push(array, ...items) {
  items.forEach(function (item) {
    array.push(item)
  })
}

let a: any[] = []

push(a, 1, 2, 3)

事实上 items 是一个数组,所以我们可以用数组的类型来定义它

function push(array: any[], ...items: any[]) {
  items.forEach(function (item) {
    array.push(item)
  })
}

let a = []
push(a, 1, 2, 3)

重载

重载允许一个函数接受不同数量或类型的参数时,作出不同的处理

比如,我们需要实现一个函数 reverse,输入数字 123 的时候,输出反转的数字 321,输入字符串 ‘hello’ 的时候,输出反转的字符串 ‘olleh’

利用联合类型,我们可以这样实现:

function reverse(x: number | string): number | string {
  if (typeof x === 'number') {
    return Number(x.toString().split('').reverse().join(''))
  } else if (typeof x === 'string') {
    return x.split('').reverse().join('')
  }
}

然而这样有一个缺点,就是不能够精确的表达,输入为数字的时候,输出也应该为数字,输入为字符串的时候,输出也应该为字符串。

  • 我们可以使用重载定义多个 reverse 的函数类型

function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string {
    if (typeof x === 'number') {
        return Number(x.toString().split('').reverse().join(''));
    } else if (typeof x === 'string') {
        return x.split('').reverse().join('');
    }
}

文章作者: 雾烟云
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 雾烟云 !
  目录