Typescript中函数类型及示例详解
疆~ 人气:0不给参数定义类型,会报错,如下:
常见写法
function add1(x: number, y: number) { return x + y; } function add1_1(x: number, y: number): number { return x + y; } const add2 = function (x: number, y: number): number { return x + y; }; const add3 = (x: number, y: number): number => x + y; const add3_1 = (x: number, y: number) => x + y; const add4: { (x: number, y: number): number } = (x: number, y: number): number => x + y; type TAdd = { (x: number, y: number): number } const add5: TAdd = (x: number, y: number): number => x + y; const add5_1: TAdd = function (x: number, y: number): number { return x + y; }; interface IAdd { (x: number, y: number): number } const add6: IAdd = (x: number, y: number): number => x + y; const add6_1: TAdd = function (x: number, y: number): number { return x + y; };
函数名赋值:
const abs0: (x: number) => number = Math.abs; const abs1: { (x: number): number } = Math.abs; type TAbs = { (x: number): number } const abs3: TAbs = Math.abs; interface IAbs { (x: number): number } const abs4: IAbs = Math.abs; console.log(abs0(23) === abs1(23)); // true console.log(abs0(23) === abs3(23)); // true console.log(abs0(23) === abs4(23)); // true
可选参数
在JavaScript中,函数的每一个参数都是可选参数,而在TypeScript中,默认情况下函数的每一个参数都是必选参数。在调用函数时,编译器会检查传入实际参数的个数与函数定义中形式参数的个数是否相等。如果两者不相等,则会产生编译错误。如果一个参数是可选参数,那么就需要在函数类型定义中明确指定。
在函数形式参数名后面添加一个问号“?”
就可以将该参数声明为可选参数。
function add(x: number, y?: number, z?: number) { return x + (y ?? 0); }
函数的可选参数必须位于函数参数列表的末尾位置。在可选参数之后不允许再出现必选参数,否则将产生编译错误。
默认参数
如果函数定义了默认参数,并且默认参数处于函数参数列表末尾的位置,那么该参数将被视为可选参数,在调用该函数时可以不传入对应的实际参数值。
function add(x: number, y: number = 0) { return x + y; } console.log(add(1)); // 1 console.log(add(1, 2)); // 3
同一个函数参数不允许同时声明为可选参数和默认参数,否则将产生编译错误
如果默认参数之后存在必选参数,那么该默认参数不是可选的参数,在调用函数时必须传入对应的实际参数值
function add(x: number = 0, y: number) { return x + y; } add(1); // 编译错误 add(1, 2); // 正确 add(undefined, 2); // 正确
剩余参数
必选参数、可选参数 和 默认参数 处理的都是单个参数,而剩余参数处理的则是多个参数。如果函数定义中声明了剩余参数,那么在调用函数时会将多余的实际参数收集到剩余参数列表中。因此,剩余参数的类型应该为数组类型或元组类型。
数组类型的剩余参数
最常见的做法是将剩余参数的类型声明为数组类型。在调用定义了剩余参数的函数时,剩余参数可以接受零个或多个实际参数
function f(...args: number[]) { console.log("args:", args) } f(); f(0); f(0, 1);
元组类型的剩余参数
如果剩余参数的类型为元组类型,那么编译器会将剩余参数展开为独立的形式参数声明,主要包括以下几种情况:
常规元组类型:
function f0(...args: [boolean, number]) { } // 等同于: function f1(args_0: boolean, args_1: number) { }
带有可选元素的元组类型:
function f0(...args: [boolean, number]) { } // 等同于: function f1(args_0: boolean, args_1: number) { }
带有剩余元素的元组类型:
function f0(...args: [boolean, ...string[]]) { } // 等同于: function f1(args_0: boolean, ...args_1: string[]) { }
在了解了元组类型剩余参数的展开行为后,我们也就清楚了该如何传入对应的实际参数,如下所示:
function f0(...args: [boolean, number, string]) { } f0(true, 0, ''); function f1(...args: [boolean, number, string?]) { } f1(true, 0, ''); f1(true, 0); function f2(...args: [boolean, number, ...string[]]) { } f2(true, 0); f2(true, 0, ''); f2(true, 0, '', 'coolcou'); function f3(...args: [boolean, number?, ...string[]]) { } f3(true); f3(true, 0); f3(true, 0, ''); f3(true, 0, '', 'coolcou');
解构参数
解构还可以应用在函数参数列表中。
未给解构参数添加类型将会报错,如下:
可以使用类型注解为解构参数添加类型信息
function f0([x, y]: [number, number]) { } f0([0, 1]); function f1({ x, y }: { x: number; y: number }) { } f1({ x: 0, y: 1 });
重载函数
参考:
TypeScript重载函数,重载函数是指一个函数同时拥有多个同类的函数签名。例如,一个函数拥有两个及以上的调用签名,或者一个构造函数拥有两个及以上的构造签名。当使用不同数量和类型的参数调用重载函数时,可以执行不同的函数实现代码。 TypeScript中的重载函数与其他编程语言中的重载函数略有不同。 下例中定义了一个重载函数add。它接受两个参数,若两个参数的类型为number,则返回它们的和;若两个参数的类型为数组,则返
构造函数类型字面量
如JavaScript提供了一个内置的Error构造函数,它接受一个可选的message
作为参数并返回新创建的Error对象
const a = new Error(); const b = new Error('Error message.');
我们可以使用如下构造函数类型字面量来表示Error构造函数的类型。该构造函数有一个可选参数message
并返回Error类型的对象
let ErrorConstructor: new (message?: string) => Error;
构造签名
若在对象类型中定义了构造签名类型成员,那么我们称该对象类型为构造函数类型。构造签名的语法如下:
{ new (ParameterList): Type }
在该语法中,new
是运算符关键字,ParameterList
表示构造函数形式参数列表类型,Type
表示构造函数返回值类型,两者都是可选的。
let Dog: { new(name: string): object }; Dog = class { private name: string; constructor(name: string) { this.name = name; } }; let dog = new Dog('coolcou');
有一些函数被设计为既可以作为普通函数使用,同时又可以作为构造函数来使用。例如,JavaScript内置的“Number()”
函数和“String()”
函数等都属于这类函数。示例如下:
const a: number = Number(1); const b: Number = new Number(1);
若在对象类型中同时定义调用签名和构造签名,则能够表示既可以被直接调用,又可以作为构造函数使用的函数类型。示例如下:(报错了,不知道为什么)
declare const F: { new(x: number): Number; // <- 构造签名 (x: number): number; // <- 调用签名 }; // 作为普通函数调用 const a: number = F(1); // 作为构造函数调用 const b: Number = new F(1);
加载全部内容