首页 > 其他分享 >Typescript 函数详解

Typescript 函数详解

时间:2023-12-24 12:33:10浏览次数:47  
标签:Typescript 函数 number add 详解 参数 类型 声明

前言

虽然 JS/TS 支持面向对象编程,但大部分时候还是在写函数。函数是一等公民。本文介绍下如何在 TypeScript 中使用函数,包括:

  • 函数类型声明
  • 函数参数类型:可选参数、默认参数、剩余参数
  • 函数返回值类型
  • this 类型
  • 函数重载

函数类型

面试中经常会被问到,JS 中有哪几种数据类型。其中就会有函数类型。

JS 中的函数类型很模糊,准确来说,仅有类型的概念,却无类型的实质。好在有了 TS 强类型的加持,现在可以好好定义一个函数的类型了。

声明一个函数类型,有若干种不同的方式。比如通过 interface 定义函数类型,通过 type 声明函数类型别名,在类声明中声明函数类型等等。

但核心就一点,只关注函数参数的类型返回值的类型

下面就从函数的声明入手,来看看函数类型的使用。

函数的声明方式

有三种最简单的函数声明方式。

使用 function 关键字进行声明:

function add(a: number, b: number): number {
  return a + b
}

通过函数表达式进行声明:

let add = function (a: number, b: number): number {
  return a + b
}

或者使用箭头函数:

let add =  (a: number, b: number): number => {  
    return a + b
}

上面这三种声明函数的方式和 JS 中声明函数别无二致,就是多了两点:

  • 函数参数需要给明类型
  • 函数返回值也需要给出类型

那么函数类型到底在哪里呢?把鼠标移动到函数名字上就能看到了:

Typescript 函数详解_函数重载

Typescript 函数详解_函数重载_02

Typescript 函数详解_函数重载_03

和声明普通变量变量一样:

let name = 'kunwu'

如果没有使用类型注解,那么编译器会自动推导出类型来。上面红框标识出来的类型,就是编译器推导出来的。

函数的类型注解

函数的类型形如 (参数:类型) => 类型,所以函数的类型注解就是:

let add: (a: number, b: number) => number = function (a, b) {
  return a + b
}

通常函数的类型都比较长,此时可以使用 type 类型别名,来声明一个标识符表示该类型:

type Add = (a: number, b: number) => number

let add: Add => number = function (a, b) {
  return a + b
}

这样,声明函数类型,使用函数类型,看上去就很简洁直观了。

对象中的函数类型

函数的参数

声明函数时,可以使用类型注解声明参数类型。如果不指定类型,默认类型是 any

function add (a: number, b: number) :number {
    return a + b
}

Typescript 函数详解_函数重载_04

可选参数

可选参数使用 ? 标记,需要放到固定参数的后面:

const fn = (a: number, b?:number) => {
    if(b) {
        return a + b
    } else {
        return a
    }
}

可选参数意味着参数可传可不传。通过编译器的类型推导,可以看到好像可选参数等同于一个联合类型:

Typescript 函数详解_TypeScript_05

但其实并不等同。

可选参数表示参数可传可不传,若传则必须是指定的类型。

而直接将参数类型声明为 string|undefined,意味着这是个必传参数,必须传实参。

参数默认值

参数的默认值,在参数的类型后面使用 = 声明:

const fn = (a: number, b: number = 10): number => {
    return a + b
}

剩余参数

剩余参数是 ES6 中的一个特性,使用剩余运算符 ... 来获取函数实参中未被形参声明的变量,其取得的值是一个数组,比如:

function add(a,b, ...args) {
    console.log(args)
}

add(1,2,3,4,5)

则剩余参数 args 就等于 [3, 4, 5]。

TS 中剩余参数也要有类型声明,需要将其声明为数组类型或者元组类型。

function add(a: number, b: number, ...args: number[]) {
    console.log(c)
}

剩余参数和其他的固定参数不同。其他的固定参数声明了类型,则必须传该类型的值。而剩余参数虽然也声明了类型,但可传可不传,可传一个,可传多个,比如:

function add(a: number, b: number, ...args: number[]) {
    console.log(args)
}

add(1, 2) // [ ]
add(1, 2, 3) // [ 3 ]
add(1, 2, 3, 4) // [ 3, 4 ]

还可以将剩余参数类型声明为元组类型,元组中还可以继续使用可选参数,在参数后使用 ? 表示:

function log( ...args: [string, number, boolean?]) {
    console.log(args)
}

log('Shinichi', 17) // [ 'Shinichi', 17 ]
log('Zoro', 19, true) // [ 'Zoro', 19, true ]

函数的返回值类型

函数的返回值类型可以通过类型注解指定。如果不指定的话,TS 编译器能够根据函数体的 return 语句自动推断出返回值类型,因此我们也可以省略返回值类型。

TS 基本类型中有一个 void 类型,表示空类型,它唯一的用处就是用作函数的返回值类型。当一个函数没有 return 语句时,

Typescript 函数详解_TypeScript_06

如果函数使用 return 语句返回了 undefined 值,则返回值类型就为 undefined 而不是 void 了:

Typescript 函数详解_TypeScript_07

但是此时可以将返回值类型使用类型注解指定为 void:

Typescript 函数详解_函数重载_08

this 类型

JS 函数中到处可见 this 的身影。关于 this 的指向也是前端八股中的基础之基础。

默认情况下 TS 编译器会将函数中的 this 设为 any 类型,也就是说编译器不会对 this 做类型检查,就可以任意使用 this,比如:

function fn() {
    this.name = 'Naruto'
    this.age = 18
}

同时 TS 编译器又提供了一个编译选项 --noImplicitThis,开启后会检查 this 的类型,此时需要明确指定其类型,否则会报错,如下:

Typescript 函数详解_TypeScript_09

那么如何为 this 声明类型呢?

声明 this 类型

TS 函数中有一个特殊的 this 参数,它用来指定该函数中用到的 this 的类型,需要定义在形参的第一个位置。

还是上面的例子,要为函数中的 this 指定类型的话,这样写:

function fn(this: {name: string, age: number}) { 
  this.name = 'Naruto'
  this.xxx = 'xxx'
}

直接在函数参数列表中声明 this 类型不太优雅,可以使用 type 关键字声明别名再使用:

type Person = {name: string, age: number}

function fn(this: Person) { 
  this.name = 'Naruto'
  this.age = 18
}

当定义了 this 类型后,函数在调用时也会有所不同,需要使用 call、apply :

type Person = {name: string, age: number}

function fn(this: Person, a: number) { 
  this.name = 'Naruto'
  this.age = 18
}


fn.call({name: 'Naruto', age: 18}, 10)

fn.apply({name: 'Naruto', age: 18}, [10])

像以前那样直接调用函数是错误的:

fn(10) // X

函数重载

面向对象编程有三大特征,封装、继承和多态。多态的表现之一就是函数的重载。

函数重载,就是可以多次声明一个同名函数,但是它们的参数类型不同或者参数个数不同。这样在调用时,可以根据传入参数类型的不同,参数个数的不同,来确定执行的到底是哪一个函数。

函数重载是后端语言的概念,比如 java 中:

// 两个整数的和
public static int add(int a, int b)  {
  return a+b;
}

// 三个整数的和
public static int add(int a, int b, int c) {
 return add(a,b)+c;
}

JS 本身并不支持函数重载。如果多次声明一个函数,则后声明的会覆盖掉先声明的。但是 JS 可以利用 arguments 对象,再加上判断实参的类型,来模拟重载的功能,比如:

function add() {
   let args = Array.from(arguments)
   if(args.length == 2) {
       return args[0] + args[1]
   } else if(args.length == 3) {
        return args[0] + args[1] + args[3]
   }
}

add(1,2)
add(1, 2, 3)

TS 中多次声明一个同名函数,编译器会报错。但是 TS 提供了实现函数重载的方法:先通过 function 关键字声明重载的类型,最后写函数的实现。

function add(a: number, b: number) : number

function add(a: string, b: string) : string

function add(a: number|string, b: number | string) {
  if(typeof a === 'number' && typeof b === 'number') {
    return a + b
  }  else if(typeof a === 'string' && typeof b === 'string') {
    return a + b
  } 
}

add(1, 2)
add('10', '20')

由于在声明重载时已经确定了函数的返回值类型,在写函数实现时,就不再需要写返回值类型了。编译器会根据重载类型自动推导。

TS 的函数重载只是一种伪重载,最终还是要靠去判断类型,来执行不同的逻辑。

还有一点要注意,声明函数重载和函数实现必须写在一块,中间不能插入其他语句。

总结

本文介绍了TS 中有关函数的知识,包括函数的声明方式,如何声明函数类型,函数参数和返回值的类型,函数重载以及 this 的类型。大部分内容和 JS 中差不太多,主要是 this 类型和函数重载这两点,需要额外关注下。

标签:Typescript,函数,number,add,详解,参数,类型,声明
From: https://blog.51cto.com/u_12382805/8955199

相关文章

  • Go 语言学习指南:变量、循环、函数、数据类型、Web 框架等全面解析
    学习基础知识掌握Go语言的常见概念,如变量、循环、条件语句、函数、数据类型等等。深入了解Go基础知识的好起点是查阅Go官方文档文章链接:Go编程语言详解:用途、特性、与Python和C++的比较基本语法了解Go语言的基本语法,包括Go程序的执行方式、包引入、主函数等Go......
  • Go 语言学习指南:变量、循环、函数、数据类型、Web 框架等全面解析
    学习基础知识掌握Go语言的常见概念,如变量、循环、条件语句、函数、数据类型等等。深入了解Go基础知识的好起点是查阅Go官方文档文章链接:Go编程语言详解:用途、特性、与Python和C++的比较基本语法了解Go语言的基本语法,包括Go程序的执行方式、包引入、主函数等Go......
  • Windows下升级go版本过程详解
    安装首次安装需要在官网下载msi安装包,安装完后golang会自动设置环境变量。在命令行可以使用goversion查看版本信息。后续如果需要升级go版本,怎么做?一种通用的办法是在官网下载列表下载对应的msi安装包下载。1https://go.dev/dl/新版本会覆盖旧版本,如果只是想使用指定版......
  • SAP ABAP 更新函数(Update Function Module)执行出错的原因分析试读版
    本教程前一篇文章,我们已经介绍了SAPABAPUpdateWokeProcess和UpdateFunctionModule的基本概念。129.SAPABAPUpdateProcess(更新进程)的概念和设计动机解析回到笔者知识星球朋友的提问:我们通过一个实战例子来消化前一篇文章学到的理论知识。本教程之前介绍了SA......
  • 【Spring教程28】Spring框架实战:从零开始学习SpringMVC 之 请求与请求参数详解
    目录1设置请求映射路径1.1环境准备1.2问题分析1.3设置映射路径2请求参数2.1环境准备2.2参数传递2.2.1GET发送单个参数2.2.2GET发送多个参数2.2.3GET请求中文乱码2.2.4POST发送参数2.2.5POST请求中文乱码欢迎大家回到《Java教程之Spring30天快速入门》,本教程所有示例......
  • 详解十大经典排序算法(六):快速排序(QuickSort)
    算法原理分区(Partition):选择一个基准元素,将数组分为两个子数组,小于基准的放在左边,大于基2准的放在右边。递归排序:对左右两个子数组分别进行快速排序。合并:不需要实际的合并操作,因为在分解和递归排序阶段已经完成了排序。算法描述快速排序是一种基于分治思想的高效排序算法,由英国......
  • 无涯教程-PL/SQL - GOTO函数
    PL/SQL编程语言中的GOTO语句提供了从GOTO到同一子程序中带标签的语句的无条件跳转。注意-在任何编程语言中均不建议使用GOTO语句,因为它会使跟踪程序的控制流变得困难,从而使程序难以理解且难以修改。GOTO-语法PL/SQL中的GOTO语句的语法如下-GOTOlabel;....<<label>>......
  • Python函数的使用和示例
    在Python中,函数是一种组织和复用代码的重要方式。函数可以帮助你将代码分解成小的、可管理的部分,并且可以在不同的地方重复使用这些代码。这里是一个简单的Python函数的示例:函数定义与使用定义一个函数:函数以def关键字开始,后跟函数名和圆括号()。圆括号内可以包含参数,也可以为空。......
  • 51 单片机【外部中断、定时器中断、回调函数】
    51单片机【外部中断、定时器中断、回调函数】​ 这里的外部中断类似监听器,时时刻刻监视某引脚的电平变化;这里的定时器中断类似于定时任务,可以定时执行某函数;这里将回调函数和中断结合起来,案例里有点设计模式的味道(忘了哪个了,也可能就是感觉,关于高层不能调用低层的解决),也有点函数......
  • C语言实现面向对象的方法详解
    结构体替代类使用结构体来封装变量和函数,即可实现类似对象的功能。其中,结构体包含变量和函数指针,变量用于存储成员变量的值,函数指针用于实现成员函数的功能。而每个对象的变量是独立的,因此可以使用这种方法实现类似对象的功能。下面是一个例子,以封装一个“人”的结构体为例:typ......