typescript定义函数类型

函数类型

为函数定义类型

给函数定义类型,包括对参数和返回值的类型定义:

function add(arg1: number, arg2: number): number {
  return arg1 + arg2
}

// 箭头函数
const add = (arg1: number, arg2:number):number => {
  return arg1 + arg2
}

如果这里省略参数的类型,typescript 会默认这个参数是 any 类型;如果省略返回值的类型,那么当函数无返回值时,typescript 默认函数返回值是 void 类型,当函数有返回值时,typescript 会根据我们定义的逻辑推断出返回值的类型。

 

完整的函数类型

可以定义一个完整的函数类型,它包括参数类型和返回值类型,如下:

// 定义变量 add,指定类型为 (x: number, y: number)=> number
let add:(x: number, y: number)=> number

// 给变量赋值函数,其符合上面定义的函数类型
add = (arg1: number, arg2: number) => arg1 + arg2

可以看到函数类型中的参数名和实际函数的参数名不一致,这里需要注意,只要参数类型是匹配的,那么就认为它是有效的函数类型,而不在乎参数名是否正确。

 

使用接口定义函数类型

使用接口可以清晰地定义函数类型:

interface Add{
  (x: number, y: number): number
}

let add:Add = (arg1: number, arg2: number): number => arg1 + arg2

 

使用类型别名定义函数

类型别名是使用 type 关键字定义一个类型,可以用来定义函数类型:

type Add = (x: number, y: number) => number

let add:Add = (arg1: number, arg2: number): number => arg1 + arg2

 

函数参数

可选参数

定义函数类型时,使用 ? 来指定可选参数,但需要注意的是,可选参数必须放在必须参数后面,这跟在接口中定义可选参数不一样,在定义接口时,可选参数的位置在前在后都无所谓。

// error,x 是可选参数,放在必选参数 y 之前是错误的
type Add = (x?: number, y: number) => number

 

默认参数

默认参数与在 es6 中的实现一样,直接用 = 给出默认值。需要注意两个地方:一是默认参数的位置不讲究,它放在必选参数前后都行;二是当给默认参数指定默认值时,typescript 会识别默认参数的类型,当我们在调用函数时,如果给这个带默认值的参数传来别的类型的参数时则会报错:

let add = (x: number, y = 2) => {
  return x + y
}

add(1, '2') // error,类型“"2"”的参数不能赋给类型“number”的参数

 

可以显示地给默认参数指定类型:

let add = (x: number, y: number = 2) => {
  return x + y
}

 

剩余参数

对于不知道会传入多少参数的函数来说,在 javascript 中会使用 arguments 来获取参数列表。在 typescript 中,使用跟 es6 中一样的 ... 来将剩余参数收集到一个变量中。

const handleData = (arg1, ...arg2) => {
  console.log(arg2)
}

handleData(1,2,3,4,5,6) // [2,3,4,5,6]

 

给参数指定类型:

const handleData = (arg1: number, ...arg2: number[]) => {
  console.log(arg2)
}

 

函数重载

在一些强类型语言中,函数重载是指定义几个函数名相同,但参数个数或类型不同的函数,在调用时传入不同的参数,编译器会自动调用适合的函数。而在 javascript 中,是没有函数重载的,我们可以在函数内部判断参数的个数和类型来指定不同的处理逻辑。

const handleData = (value: any)=>{
  if(typeof value === 'string'){
    return value.split('')
  }else{
    return value.toString().split('').join('_')
  }
}

console.log(handleData('hello')) // ["h", "e", "l", "l", "o"]

console.log(handleData(123)) // 1_2_3

 

我们需要将上面这种情况在类型系统中表示出来。在 typescript 中有函数重载的概念,但不是定义几个同名实体函数,而是通过为一个函数指定多个函数类型定义,从而对函数调用的返回值进行检查。代码如下:

function handleData(value: string): string[]
function handleData(value: number): string
function handleData(value: any):any {
  if(typeof value === 'string'){
    return value.split('')
  }else{
    return value.toString().split('').join('_')
  }
}

console.log(handleData('hello')) // ["h", "e", "l", "l", "o"]

console.log(handleData(123)) // 1_2_3

console.log(handleData(false)) // error,类型“false”的参数不能赋给类型“string”的参数,类型“false”的参数不能赋给类型“number”的参数

首先使用 function 关键字定义了两个同名函数,这两个函数没有实际的函数体逻辑,只定义了函数名,参数及参数类型以及函数的返回值类型,这两个定义称为 “函数重载”。第三个使用 function 定义的同名函数,是一个完整的实体函数,它不算重载。这三个定义组成一个函数。当函数调用时,会从上到下匹配重载,当匹配不到时会报错。

 

posted @ 2020-05-09 16:00  黑色瓶子  阅读(14556)  评论(0编辑  收藏  举报