TypeScript 学习笔记(六):函数类型

前言

在上一篇文章TypeScript 学习笔记(五):interface接口中我们学习了TSinterface接口,本篇文章我们主要了解TS中的函数

介绍

函数是JavaScript应用程序的基础。 它帮助你实现抽象层,模拟类,信息隐藏和模块。 在TypeScript里,虽然已经支持类,命名空间和模块,但函数仍然是主要的定义行为的地方。 TypeScript为JavaScript函数添加了额外的功能,让我们可以更容易地使用。

TS中,函数的定义和JS一样,不过是添加了类型的约束。以下是TS中函数的两种写法案例。

TS 复制代码
// 写法一
const hello = function (txt:string) {
  console.log('hello ' + txt);
}

// 写法二
const hello:
  (txt:string) => void
= function (txt) {
  console.log('hello ' + txt);
};
  • 写法一是通过等号右边的函数类型,推断出变量hello的类型。
  • 写法二则是使用箭头函数的形式,为变量hello指定类型,参数的类型写在箭头左侧,返回值的类型写在箭头右侧。

写法二有两个地方需要注意:

第一,函数的参数要放在圆括号里面,不放会报错。 第二,类型里面的参数名是必须的。如果写成(string) => void,TypeScript 会理解成函数有一个名叫 string 的参数,并且这个string参数的类型是any,如以下例子。

TS 复制代码
type MyFunc = (string, number) => number;
// (string: any, number: any) => number

只要参数类型是匹配的,那么就认为它是有效的函数类型,而不在乎参数名是否正确。 意思就是函数类型里面的参数名与实际参数名,可以不一致。

TS 复制代码
let myAdd: (baseValue: number, increment: number) => number =
    function(x: number, y: number): number { return x + y; };

Function类型

TS提供Function类型表示函数,任何函数都属于这个类型。

TS 复制代码
function doSomething(f:Function) {
  return f(1, 2, 3);
}

Function 类型的函数可以接受任意数量的参数,每个参数的类型都是any,返回值的类型也是any,代表没有任何约束。

函数的参数

TS里的每个函数参数都是必须的。这不是指不能传递 nullundefined作为参数,而是说编译器检查用户是否为每个参数都传入了值。 编译器还会假设只有这些参数会被传递进函数。 简单地说,传递给一个函数的参数个数必须与函数的参数个数一致。

TS 复制代码
function buildName(firstName: string, lastName: string) {
    return firstName + " " + lastName;
}

let result1 = buildName("Bob");                  // 报错,少了
let result2 = buildName("Bob", "Adams", "Sr.");  // 报错,多了
let result3 = buildName("Bob", "Adams");         // 正确

可选参数

JS中,每个参数都是可传可不传。没传参的时候,默认值是undefined这一点在TS里,我们可以使用?实现可选参数的功能。

TS 复制代码
function buildName(firstName: string, lastName?: string) {
    if (lastName)
        return firstName + " " + lastName;
    else
        return firstName;
}

参数名带有问号,表示该参数的类型实际上是原始类型|undefined,它有可能为undefined

比如,下面例子的x虽然类型声明为number,但是实际上是number|undefined。等同于说x可以赋值为undefined

TS 复制代码
function f(x?:number) {
  return x;
}

f(undefined) // 正确

但是,反过来就不成立,类型显式设为undefined的参数,就不能省略。

javascript 复制代码
function f(x:number|undefined) {
  return x;
}

f() // 报错

上面示例中,参数x的类型是number|undefined,表示要么传入一个数值,要么传入undefined,如果省略这个参数,就会报错。

可选参数必须跟在必须参数后面。 通俗的讲,就是有?的必须在没有?的参数后面。

TS 复制代码
let myFunc:
  (a?:number, b:number) => number; // 报错

上面示例中,可选参数在必选参数前面,就报错了。

默认参数

TS的默认参数写法,与JS一样。

设置了默认值的参数,就是可选的。如果不传入该参数,它就会等于默认值。

TS 复制代码
function createPoint(
  x:number = 0,
  y:number = 0
):[number, number] {
  return [x, y];
}

createPoint() // [0, 0]

所以可选参数与默认值不能同时使用。 下面例子中,x是可选参数,还设置了默认值,结果就报错了。

TS 复制代码
// 报错
function f(x?: number = 0) {
  // ...
}

rest参数

rest参数表示函数剩余的所有参数,它可以是数组(剩余参数类型相同),也可能是元组(剩余参数类型不同)。

TS 复制代码
// rest 参数为数组
function joinNumbers(...nums:number[]) {
  // ...
}

// rest 参数为元组
function f(...args:[boolean, number]) {
  // ...
}

下面是一个rest参数的例子。

TS 复制代码
function multiply(n:number, ...m:number[]) {
  return m.map((x) => n * x);
}

rest 参数可以嵌套。

TS 复制代码
function f(...args:[boolean, ...string[]]) {
  // ...
}

rest 参数可以与变量解构结合使用。

TS 复制代码
function repeat(
  ...[str, times]: [string, number]
):string {
  return str.repeat(times);
}

// 等同于
function repeat(
  str: string,
  times: number
):string {
  return str.repeat(times);
}

readonly只读参数

如果函数内部不能修改某个参数,可以在函数定义时,在参数类型前面加上readonly关键字,表示这是只读参数。

TS 复制代码
function arraySum(
  arr:readonly number[]
) {
  // ...
  arr[0] = 0; // 报错
}

上面示例中,参数arr的类型是readonly number[],表示为只读参数。如果函数体内部修改这个数组,就会报错。 但是,readonly关键字目前只允许用在数组和元组类型的参数前面,如果用在其他类型的参数前面,就会报错。

相关推荐
腾讯TNTWeb前端团队6 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰10 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪10 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪10 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy11 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom11 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom11 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom12 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom12 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom12 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试