TypeScript从0基础到项目实战:06.函数类型

126 阅读3分钟

1. 函数类型的基础定义

显式指定函数参数和返回值的类型

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

或者用type来声明函数类型

 type addFnType = (a: number, b:number) => number;
 let addFn: addFnType = (num1, num2) => {
     return num1 + num2;
 }

2. 函数参数类型

参数一般有:可选参数、默认参数、剩余参数;

1. 可选参数

在类型标注的:前添加?表示 log 函数的参数 x 就是可缺省的;

 function log(msg?: string):void {
     console.log(msg);
 }

可缺省是不是相当于msg参数的类型就是和string | undefined等价呢?这个当然不是,string | undefined的意思是这两个类型中的一种,而可缺省是不传的意思。

2. 默认参数

 function addFn1(num1: number = 1, num2: number = 2):number {
     return num1 + num2;
 }

函数的默认参数类型必须是参数类型的子类型

 function log3(x: number | string = 'hello') {
     console.log(x);
 }

这里x参数的类型就是联合类型number | string,函数默认参数的类型就是联合类型的子类型

3. 剩余参数

 function sum(...nums: number[]) {
     return nums.reduce((a, b) => a + b, 0);
 }
 sum(1, 2); // => 3
 sum(1, 2, 3); // => 6

4. this

函数中的this问题,一直都是javascript最令人头疼的问题,因为this的指向只有函数调用的时候才能确定。还有一些可以改变this指向的方法(apply,call,bind)。

但是在Typescript中,必须要明确的指定this的类型(严格模式下)。

 export {};
 type objType = {person: (n: string) => void, myname: string};
 // ts提供了Window(W大写)类型,而我们常用的window就是它的对象
 function person(this: Window | objType , name: string):void {
     //我们想要给window上添加东西,需要通过interface拓展,
     //但是Window类型必须在全局(也就是不在是export{}一个空)才能接受拓展
     //所以我们可以定义一个global.d.ts文件来专门写这种全局的拓展
     this.myname = name;
     console.log(this.myname);
 }
 ​
 window.person = person; //在本文件中我们写了export{},所以window仍然不是全局的,
                      //所以这里的函数person并没有挂载在window上,我们手动挂载
 window.person('window name');
 let obj:objType = {
     person,
     myname: ''
 };
 obj.person('obj name');

注意:为什么我们这里的this声明的类型是Window?因为它在最外层,而调用这个函数的也是window,this的类型必须和调用它的类型一致

单单是上面的代码是有问题的,我们还需要创建一个类型声明文件global.d.ts,(其实就是你随便写一个文件,这个文件不使用export{};让里面的代码暴露,因为window只有在全局下才能接受你的拓展)为window对象上扩展两个属性person、myname;

 interface Window {
   person: (n: string) => void;
   myname: string;
 }

定义对象的函数属性时,只要实际调用中 this 的指向与指定的 this 指向不同,TypeScript 就能发现 this 指向的错误

 interface ObjType2 {
     name: string;
     say: (this: ObjType2) => void;
 }
 let obj2:ObjType2 = {
     name: 'obj2',
     say() {
         console.log(this.name);
     }
 } 
 ​
 obj2.say(); // ok
 ​
 let t11 = obj2.say;
 t11();

注意:

  1. 显式声明函数的返回值类型为 undfined,则会出现错误提示,如果没有返回值,我们用void表示;
  2. 显式注解函数中的 this 类型,它表面上占据了第一个形参的位置,但并不意味着函数真的多了一个参数,因为 TypeScript 转译为 JavaScript 后,“伪形参” this 会被抹掉,这算是 TypeScript 为数不多的特有语法。