TypeScript 函数
函数是JavaScript和Typescript的重要组成部分。函数有几个类型方面,我们需要了解:
参数类型 - 单独参数的类型
返回类型 - 返回值的类型(如果有)
参数的数量
可选参数(JavaScript中常用的特性)
默认参数值
参数和返回值的类型插入方式与前面章节中的基本类型类似。例如,下面是一个简单函数的声明,用于将两个数字相乘。
function product( num1: number, num2: number) : number {
return num1 * num2;
}
还有另一种方法来声明类似插入类型的 JavaScript 函数:
let product =
function product(num1: number, num2: number) : number {
return num1 * num2;
}
这两个声明定义相同的函数。但是,第二个使用分配给变量的匿名函数声明。此技术具有导入属性,即自动键入变量(在本例中为函数名称)。它没有类型注释。
为了完全指定函数类型,我们使用特殊的语法。上述函数具有以下类型:
( n1: number, n2:number) => number
此处,括号括在参数列表类型之后,返回类型跟在 => 符号后面。这意味着我们可以完全注释我们的函数声明,如下所示。
let product : (n1: number, n2:number) => number
= function product(num1: number, num2: number) : number {
return num1 * num2;
}
请注意类型占位符(n1 和 n2)的名称与函数定义中的实际参数名称(num1 和 num2)不同。这并不重要,尽管如果您愿意,可以使用相同的名称。
在正常实践中,我们不会担心双精度类型规范,而是依赖于从匿名函数定义中自动派生类型。但是,在某些地方,完整的功能类型规范很有用。有时我们希望将函数作为参数,这允许我们指定它们的类型。例如,以下函数采用的参数是上述类型的函数:
let f = function(list : number[],
op: (n1: number, n2:number) => number) {
// code to process list
}
然后,我们可以在调用中将上面的函数与名为 list1 的数字数组一起使用:
var n:number = f(list1, product);
在 JavaScript 中,我们可以有灵活数量的参数。打字稿不灵活。必须正确键入有关参数数量的所有可能性,当参数数量不正确时,Typescript 将产生错误。有几种方法可以指定参数的数量。
指定不同数量的参数的第一种方法是可选参数。这是通过在参数名称后放置“?”符号来完成的。例如,在下面的函数中,第二个参数是可选的。
function salutation( firstName: string, nickname?: string) : string {
if (nickname) {
return "Hi " + nickname;
} else {
return "Hi " + firstname;
}
}
在这里,nickname是可选参数。请注意,if语句对可选参数的值进行了undefined(或null)的测试,这在JavaScript中返回false。
我们还可以使用默认参数,这与您使用过的其他语言非常相似。例如,我们可以给下面的函数中的title参数分配一个默认值。
function salutation( firstName: string, title = "Ms") : string {
return "Hi " + title + nickname;
}
请注意,这个声明使用了默认值参数的推断类型。如果我们想要完整写出来,可以写成"title:string = ‘Ms’"。
参数类型的最后一种类型是当我们有未指定数量的参数时。以下是一个例子。
function product( num1 : number, ...rest: number[]) : number {
let prod = num1;
for (let i:number = 0; i<rest.length; i++) {
prod *= rest[i];
}
return prod;
}
这里的...
符号引入了可选参数,它们被指定并作为数组进行访问。例如,我们可以使用五个可选参数调用该函数,并将它们放置在剩余数组参数中以在函数内部访问:
let prod = product(1, 2, 3, 4, 5, 6);
以下是一些进一步的函数定义示例。
函数类型有两个主要方面。首先是函数定义中插入的类型。然后是用于抽象地指定函数类型的类型语法。
在函数定义中插入类型时,有四个类型要求。它们是:
- 参数类型。我们像之前看到的变量声明一样追加类型。
- 函数返回类型。这是函数返回的值的类型。
- 参数的数量。JavaScript允许向函数传递任意数量的参数。但是Typescript要求我们需要指定每个参数的类型。
- 可选参数。我们可以将参数指定为可选,并在没有提供参数时指定参数的默认值。
我们将从一个简单的函数开始,该函数具有固定数量的参数并返回一个数字。
function add(num1: number, num2:number) : number {
return num1+num2;
}
这个非常简单的函数有两个数字参数并返回一个数字。我们可以简单地使用这个函数写入控制台,如下所示:
console.log(add(23,24));
这将在控制台上显示 47。我们可以扩展此函数以具有可选的第三个参数。
function add2(num1: number, num2:number, num3?:number) : number {
if (num3) {
return num1+num2+num3;
} else {
return num1+num2;
}
}
语法`num3?`表示一个可选参数。请注意,我们可以在函数中通过`if(num3)`语句测试它是否存在。以下两个函数调用都将起作用。
console.log(add2(23,24));
console.log(add2(23,24,25));
有了可选参数后,我们还可以为参数添加默认值。这类似于可选参数,但这意味着参数在函数中始终可用,因此我们不必测试它们的存在。例如,我们可以使用默认值重写上述函数,并且该函数可以以完全相同的方式使用。
function add3(num1: number, num2:number, num3:number=0) : number {
return num1+num2+num3;
}
console.log(add3(23,24,25));
console.log(add3(23,24));
我们还可以指定一个参数列表,允许在参数调用中插入任意数量的参数。我们通过引入一个参数数组来做到这一点,其中包含...象征。以下版本的加法器函数有一个固定参数,后跟一个零个其他参数。
function add4(num1 : number, ...rest: number[]) : number {
let sum = num1;
for (let i:number = 0; i<rest.length; i++) {
sum += rest[i];
}
return sum;
}
作为其使用的示例,以下函数调用将在控制台上将数字从 1 添加到 6。
console.log(add4(1,2,3,4,5,6));
重要的是要意识到,在TypeScript中,参数数组意味着列表末尾的所有参数必须是相同类型的。只能使用一个参数数组,并且它必须是参数定义列表中的最后一个参数。
我们还应该注意,add4()
的定义故意至少有一个参数。我们可以定义一个类似的函数,它可以接受零个参数,如下所示。
function add5( ...nums: number[]) : number {
let sum = 0;
for (let i:number = 0; i<nums.length; i++) {
sum += nums[i];
}
return sum;
}
在对add4()
和add5()
进行调用时唯一的区别是,add5()
可以使用零个参数。
TypeScript 函数定义
函数类型的第二部分是函数类型的独立定义。这些允许我们指定函数参数,并在需要函数类型的其他地方使用。
假设我们有一个函数,它接受单个数字参数并返回一个字符串。这可以指定为类型:
(p1:number) => string
此处,括号括在参数周围,函数返回类型位于 => 符号的右侧。这可以扩展到多个参数或零个参数,如以下示例所示。
(p1:number, p2:string, p3:number) => string
() => number
我们可以在函数定义中使用函数类型。例如,下面是一个完全指定的函数,用于将两个数字相加:
let sum: (n1:number, n2:number) => number =
function (num1:number, num2:number):number {
return num1+num2;
}
这通常不是这样写的,因为程序员和 Typescript 只需查看参数定义就可以充分推断出函数类型。请注意类型定义中的参数与实际定义中的参数的名称不同。这并不重要,但您可能希望使用含义标识符来帮助记录代码。
函数类型定义的常见用法是将函数作为参数传递给其他函数。例如,以下函数将类型为 (n1:number, n2:number) => number 的任何函数作为参数:
let myApply = function(fun: (n1:number, n2:number) => number) {
console.log(fun(2,3));
}
现在我们可以尝试使用上面的 sum() 函数作为参数的 console.log() 调用这个函数,在控制台上打印 “5”,如下所示:
console.log(myApply(sum));
现在,使用函数作为其他函数的参数是一个困难的概念,但它用于我们将使用的框架中。这个想法是以函数的形式将可调用的代码传递给框架定义的函数。花一些时间了解此示例的工作原理。
将函数分配给变量
在 TypeScript 中,你可以使用箭头函数类型来定义函数的类型,并将其赋值给变量。让我重新介绍一下你提到的例子:
let f: (n: string, age: number) => string;
f = function(name: string, age: number): string {
return `My name is ${name} and I am ${age} years old.`;
};
console.log(f("Alice", 25)); // 输出: My name is Alice and I am 25 years old.
在上面的代码中,我们定义了一个变量 f
,它的类型是一个接受一个 string
类型和一个 number
类型参数,并返回一个 string
类型的函数。然后,我们将一个具有相同参数和返回类型的函数赋值给 f
。
这意味着我们可以使用 f
变量来调用这个函数,就像我们调用一个普通的函数一样。在这个例子中,我们将名字和年龄作为参数传递给 f
函数,并将返回的字符串输出到控制台上。
通过这种方式,我们可以定义具有特定参数和返回类型的函数,并将它们赋值给变量,以便在需要时使用。这种灵活性使得在 TypeScript 中编写函数更加强大和可维护。
样题
(1)
以下是一个 TypeScript 函数头:
function getData(name:string, age:number) : string { … }
如何指定一个变量或参数,可以被赋予该类型的函数。请选择正确的答案:
要指定可以被赋予该类型函数的变量或参数,你可以使用 TypeScript 中的 type
或 interface
语法。以下是你可以选择的选项:
function f:(n:string,age:number):string;
let f:(n:string,age:number):string {...}
let f:(n:string,age:number)=>string;
function f:(n:string,age:number):string {..}
答案:
let f:(n:string,age:number)=>string;
(2)
以下是一个 JavaScript 函数头:
function getData(name, studentID) { … return “”+name+”,”+e-mail; …. }
如果 name
是一个字符串,studentID
是一个整数,返回值是一个字符串。在 TypeScript 中,如何完全指定函数头中的类型。请选择正确的答案:
function getData(name:string,studentlD:number):string
{…}
getData(name:string,studentlD:number)=>string
{.…}
let getData(name:string,studentlD:number)=>string
{…}
void getData(name,studentlD)
{…}
答案:
function getData(name:string,studentlD:number):string
{…}