TypeScript⼊门三:TypeScript函数类型
TypeScript函数类型
TypeScript函数的参数
TypeScript函数的this与箭头函数
TypeScript函数重载
⼀、TypeScript函数类型
在上⼀篇博客中已经对声明TypeScript类型变量已经做了初步的解析,这⾥先回顾以下:
1//声明函数
2function add1(x:number,y:number):number{
3return x+y;
4 }
5
6 let add2 = function(x:number,y:number):number{
7return x + y;
8 }
9
10//定义函数类型
11 type myAdd = (baseValue: number, increment: number) => number;
12//根据函数类型声明函数变量
13 let myAdd1:myAdd = function(x:number,y:number) : number{
14return x + y;
15 }
16 let myAdd2:myAdd = function(x:number,y:number) : number{
17return x - y;
18 }
19
20 let hintStamp(str:string):void{
21  console.log(str);
22 }
关于函数类型有⼀点需要注意,需要使⽤type关键字并使⽤等号"="赋值类型;如果使⽤let声明并使⽤冒号冒“:”表⽰的是声明⼀个函数变量,并且这个函数变量有指定的类型,这个变量不能作为函数类型,只能给它⾃⼰赋值指定类型的函数。
⼆、TypeScript函数的参数
2.1 根据函数类型声明的函数变量,函数的实际参数名称可以不与函数类型的参数名称⼀致,这⼀点与
对象类型Object的字段有点区别;
1 type myAdd = (baseValue: number, increment: number) => number;
2 let myAdd1:myAdd = function(a:number,b:number) : number{
3return a + b;
4 }
5 let myAdd2:myAdd = function(x:number,y:number) : number{
6return x - y;
7 }
2.2 可选参数与默认参数:
这部⾮内容在官⽅⽂档中有详细的说明,这⾥简要的解析以下,如果有不明⽩的建议查看官⽅⽂档。
可选参数意思就是函数的参数在实际调⽤函数时,可以不需要全部对应传⼊,但是在定义函数类型时,必须设定默认参数。
1//⽰例:在定义函数类型时,给参数b设定了默认参数:'TypeScript'
2function foo (a: string,b = 'TypeScript'): void{
3  console.log(a + ':' + b);
4 }
5 foo('hello');//hello:TypeScript
设置了默认参数,就不需要设置参数的类型了,TypeScript的IDE会主动为我们推断出参数的类型,也就是默认值的类型,如果给可选参数传值就必须对应默认参数的类型。
除了设置既定的默认参数以外,还可以使⽤(参数名+?)的⽅式设置⾮特定参数,但是设置默认⾮特定参数需要设置默认参数的类型(参数名?:类型)。这种不设定特定值的可选参数,调⽤函数时不给这个可选参数传值的话就会默认为undefined。
1//这是官⽅⽂档中的⼀个⽰例:
2function buildName(firstName: string, lastName?: string) {
3if (lastName){
4
5return firstName + " " + lastName;
6  }else{
7return firstName;
8  }
9 }
10
11 let result1 = buildName("Bob");  // works correctly now
12 console.log(result1);
13 let result2 = buildName("Bob", "Adams", "Sr.");  // error, too many parameters
14 let result3 = buildName("Bob", "Adams");  // ah, just right
2.3 剩余参数
关于剩余参数其本质就是ES6的收集(res)语法,使⽤"..."将多余的参数收集,但是TypeScript转换到ES5的js代码时还是需要使⽤arguments来实现,毕竟ES5版本中还没有收集(res)语法。详细可以了解
1function buildName(firstName: string, ...restOfName: string[]) {
2return firstName + " " + restOfName.join(" ");
3 }
4
5 let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");
但是需要注意,收集语法产⽣的数据必然是数组,所以必须使⽤数组类型。
三、TypeScript函数的this与箭头函数
关于this指向在JavaScript中⼀直是⽐较容易被它击晕的⼀个知识点,不要担⼼,我这⾥有⼀篇博客包治百病:
当然ES6的相关语法产⽣的this指向规则变化这⾥也有:
当然好不了严格模式的this指向问题:
TypeScript并不改变JavaScript的this指向规则,⽽是在IDE中提供了更友好的警告提⽰,这个功能需要在tsconfig.json中通过"noImplicitThis": true开启。我们知道在JavaScript中this指向规则是⽐较复杂的,⽽TypeScript也根据这些规则做出了相应的调整,这⾥关于TypeScript函数的this指向其实就是了解"noImplicitThis"给我们的提⽰规则是什么?
3.1 TypeScript对象返回函数中的this会警告提⽰:
1 let obj = {
2  strs : ["aaa","bbb","ccc","ddd"],
3  fun:function(){
4return function() { //这⾥会提⽰this出错,因为在严格模式下this可能为undefined,在TypeScript中IDE识别this类型为any,所以被认为可能出现undefined情况
5      let index = Math.floor(Math.random() * this.strs.length);
6return this.strs[index];
7    }
8  }
9 }
10var fun = obj.fun();
11 console.log(fun());
这个问题可以使⽤箭头函数来解决:
1 let obj = {
2  strs : ["aaa","bbb","ccc","ddd"],
3  fun:function(){
4return () => { //通过箭头函数解决
5      let index = Math.floor(Math.random() * this.strs.length);
6return this.strs[index];
7    }
8  }
9 }
10var fun = obj.fun();
11 console.log(fun());
3.2 this作为函数参数,不会出现错误提⽰,这⼀点需要注意,因为在原⽣JavaScritp种这种写法会直接出现语法错误。例如⽰例中这样写:1function f(this:void){//这⾥你可以给形参任意TypeScript类型都不会报错
2//很遗憾这⾥并不会报错
3 }
这⾥有⼏⽅⾯的原因,严格模式下函数只执⾏内部this都是指向undefined,如果函数被对象调⽤this必然也就指向调⽤函数的对象。更关键的是被写在形参内的this根本就不会被TypeScript编译到原⽣js代码中,这⾥不报错其实是TypeScript将这个低级的错误帮你⾃动处理了,所以就静默了这个错误提⽰。
关于this作为参数在TypeScript中还有另⼀个功能,就是帮助函数维持this指向,例如官⽅这个⽰例:
1 interface Card {
2    suit: string;
3    card: number;
4 }
5 interface Deck {
6    suits: string[];
7    cards: number[];
8    createCardPicker(this: Deck): () => Card;
9 }
10 let deck: Deck = {
11    suits: ["hearts", "spades", "clubs", "diamonds"],
12    cards: Array(52),
13// NOTE: The function now explicitly specifies that its callee must be of type Deck
14    createCardPicker: function(this: Deck) {js arguments
15return () => {
16            let pickedCard = Math.floor(Math.random() * 52);
17            let pickedSuit = Math.floor(pickedCard / 13);
18
19return {suit: this.suits[pickedSuit], card: pickedCard % 13};
20        }
21    }
22 }
23
24 let cardPicker = ateCardPicker();
25 let pickedCard = cardPicker();
26
27 alert("card: " + pickedCard.card + " of " + pickedCard.suit);
上⾯这段代码中14⾏的createCardPicker: function(this: Deck){}被编译成了这样:
1 createCardPicker: function () {
2var _this = this;
3 }
上⾯这种代码是我们常⽤维持this指向的⼿段,在定义接⼝时常见的代码,在TypeScript中它使⽤this作为参数的⽅式来实现,这样的处理⽅式可以⾮常明显的看到this指向了对象⾃⾝,并且如果这个⽅法被赋值给其他对象变量时同样会静默这个this参数的错误,⽽其他对象在TypeScript严格的变量类型语法中也可能获取这个⽅法作为⾃⾝参数。
3.3 this在回调函数中如何维持this指向?下⾯是将官⽅⽂档代码补全的⽰例:
1 interface UIElement {
2  addClickListener(onclick: (this: void, e: Event) => void): void;
3 }
4
5 class Handler {
6  info: string;
7  constructor(infoStr:string){
8this.info = infoStr;
9  }
10  onClickGood = (e: Event) => {//通过箭头函数来保持函数内部this不变
11// can't use this here because it's of type void!
12      console.log(this);//指向Handler的实例对象
13      console.log(this.info);//info
14      console.log('clicked!');
15  }
16 }
17 let h = new Handler('info');
18 class uiElementClass implements UIElement{
19  addClickListener(onclick: (this: void, e: Event) => void): void{
20    onclick(new Event('event'));
21  }
22 }
23 let uiElement:uiElementClass = new uiElementClass();
24 uiElement.ClickGood);
四、TypeScript函数重载
关于TypeScript函数我想了好久就是不知道怎么解析这个东西,照着⽰例套吧,我也只能复制官⽅代码放这⾥了。
1 let suits = ["hearts", "spades", "clubs", "diamonds"];
2
3function pickCard(x: {suit: string; card: number; }[]): number;
4function pickCard(x: number): {suit: string; card: number; };
5function pickCard(x:any): any {
6// Check to see if we're working with an object/array
7// if so, they gave us the deck and we'll pick the card
8if (typeof x == "object") {
9        let pickedCard = Math.floor(Math.random() * x.length);
10return pickedCard;
11    }
12// Otherwise just let them pick the card
13else if (typeof x == "number") {
14        let pickedSuit = Math.floor(x / 13);
15return { suit: suits[pickedSuit], card: x % 13 };
16    }
17 }
18
19 let myDeck = [{ suit: "diamonds", card: 2 }, { suit: "spades", card: 10 }, { suit: "hearts", card: 4 }];
20 let pickedCard1 = myDeck[pickCard(myDeck)];
21 alert("card: " + pickedCard1.card + " of " + pickedCard1.suit);
22
23 let pickedCard2 = pickCard(15);
24 alert("card: " + pickedCard2.card + " of " + pickedCard2.suit);

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。