TypeScript入门三:TypeScript函数类型

  • TypeScript函数类型
  • TypeScript函数的参数
  • TypeScript函数的this与箭头函数
  • TypeScript函数重载

一、TypeScript函数类型

在上一篇博客中已经对声明TypeScript类型变量已经做了初步的解析,这里先回顾以下:

 1 //声明函数
 2 function add1(x:number,y:number):number{
 3   return x+y;
 4 }
 5
 6 let add2 = function(x:number,y:number):number{
 7   return x + y;
 8 }
 9
10 //定义函数类型
11 type myAdd = (baseValue: number, increment: number) => number;
12 //根据函数类型声明函数变量
13 let myAdd1:myAdd = function(x:number,y:number) : number{
14   return x + y;
15 }
16 let myAdd2:myAdd = function(x:number,y:number) : number{
17   return 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{
3   return a + b;
4 }
5 let myAdd2:myAdd = function(x:number,y:number) : number{
6   return x - y;
7 }

2.2 可选参数与默认参数:

这部非内容在官方文档中有详细的说明,这里简要的解析以下,如果有不明白的建议查看官方文档。

可选参数意思就是函数的参数在实际调用函数时,可以不需要全部对应传入,但是在定义函数类型时,必须设定默认参数。

1 //示例:在定义函数类型时,给参数b设定了默认参数:‘TypeScript‘
2 function foo (a: string,b = ‘TypeScript‘): void{
3   console.log(a + ‘:‘ + b);
4 }
5 foo(‘hello‘);//hello:TypeScript

设置了默认参数,就不需要设置参数的类型了,TypeScript的IDE会主动为我们推断出参数的类型,也就是默认值的类型,如果给可选参数传值就必须对应默认参数的类型。

除了设置既定的默认参数以外,还可以使用(参数名+?)的方式设置非特定参数,但是设置默认非特定参数需要设置默认参数的类型(参数名?:类型)。这种不设定特定值的可选参数,调用函数时不给这个可选参数传值的话就会默认为undefined。

 1 //这是官方文档中的一个示例:
 2 function buildName(firstName: string, lastName?: string) {
 3   if (lastName){
 4
 5     return firstName + " " + lastName;
 6   }else{
 7     return 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)语法。详细可以了解ES6入门一:块级作用域(let&const)、spread展开、rest收集

1 function buildName(firstName: string, ...restOfName: string[]) {
2   return firstName + " " + restOfName.join(" ");
3 }
4
5 let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");

但是需要注意,收集语法产生的数据必然是数组,所以必须使用数组类型。

三、TypeScript函数的this与箭头函数

关于this指向在JavaScript中一直是比较容易被它击晕的一个知识点,不要担心,我这里有一篇博客包治百病:JavaScript中的this指向规则

当然ES6的相关语法产生的this指向规则变化这里也有:ES6入门五:箭头函数、函数与ES6新语法

当然好不了严格模式的this指向问题:JavaScript严格模式

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(){
 4     return function() { //这里会提示this出错,因为在严格模式下this可能为undefined,在TypeScript中IDE识别this类型为any,所以被认为可能出现undefined情况
 5       let index = Math.floor(Math.random() * this.strs.length);
 6       return this.strs[index];
 7     }
 8   }
 9 }
10 var fun = obj.fun();
11 console.log(fun());

这个问题可以使用箭头函数来解决:

 1 let obj = {
 2   strs : ["aaa","bbb","ccc","ddd"],
 3   fun:function(){
 4     return () => { //通过箭头函数解决
 5       let index = Math.floor(Math.random() * this.strs.length);
 6       return this.strs[index];
 7     }
 8   }
 9 }
10 var fun = obj.fun();
11 console.log(fun());

3.2 this作为函数参数,不会出现错误提示,这一点需要注意,因为在原生JavaScritp种这种写法会直接出现语法错误。例如示例中这样写:

1 function 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) {
15         return () => {
16             let pickedCard = Math.floor(Math.random() * 52);
17             let pickedSuit = Math.floor(pickedCard / 13);
18
19             return {suit: this.suits[pickedSuit], card: pickedCard % 13};
20         }
21     }
22 }
23
24 let cardPicker = deck.createCardPicker();
25 let pickedCard = cardPicker();
26
27 alert("card: " + pickedCard.card + " of " + pickedCard.suit);

上面这段代码中14行的createCardPicker: function(this: Deck){}被编译成了这样:

1 createCardPicker: function () {
2         var _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){
 8     this.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.addClickListener(h.onClickGood);

四、TypeScript函数重载

关于TypeScript函数我想了好久就是不知道怎么解析这个东西,照着示例套吧,我也只能复制官方代码放这里了。

 1 let suits = ["hearts", "spades", "clubs", "diamonds"];
 2
 3 function pickCard(x: {suit: string; card: number; }[]): number;
 4 function pickCard(x: number): {suit: string; card: number; };
 5 function 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
 8     if (typeof x == "object") {
 9         let pickedCard = Math.floor(Math.random() * x.length);
10         return pickedCard;
11     }
12     // Otherwise just let them pick the card
13     else if (typeof x == "number") {
14         let pickedSuit = Math.floor(x / 13);
15         return { 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);

原文地址:https://www.cnblogs.com/ZheOneAndOnly/p/11780518.html

时间: 2024-10-08 05:58:50

TypeScript入门三:TypeScript函数类型的相关文章

C语言学习入门 (三) sizeof 函数、内存地址、数组

sizeof可以用来计算一个变量或者一个常量.一种数据类型所占的内存字节数. sizeof(10); char c = 'a'; sizeof(c); sizeof(float); 地址 1.计算机中的内存是以字节为单位的存储空间.内存的每一个字节都有一个唯一的编号,这个编号就称为地址. 凡存放在内存中的程序和数据都有一个地址,也就是说,一个函数也有自己的内存地址 2.  当定义一个变量时,系统就分配一个带有唯一地址的存储单元来存储这个变量.比如: char a = 'A';// A的ASCII

C语言学习入门 (三) sizeof函数、内存地址、数组

sizeof可以用来计算一个变量或者一个常量.一种数据类型所占的内存字节数. sizeof(10); char c = 'a'; sizeof(c); sizeof(float); 地址 1.计算机中的内存是以字节为单位的存储空间.内存的每一个字节都有一个唯一的编号,这个编号就称为地址. 凡存放在内存中的程序和数据都有一个地址,也就是说,一个函数也有自己的内存地址 2.  当定义一个变量时,系统就分配一个带有唯一地址的存储单元来存储这个变量.比如: char a = 'A';// A的ASCII

TypeScript入门五:TypeScript的接口

TypeScript接口的基本使用 TypeScript函数类型接口 TypeScript可索引类型接口 TypeScript类类型接口 TypeScript接口与继承 一.TypeScript接口的基本使用 1.1定义TypeScript接口的指令(interface) 接口让我们想到的第一个短语就是(API).比如日常我们所说的调用某某程序的API一般都是跨应用的接口,如别的网站的或者APP的接口:还有我们每天都是用的编程语言的指令和内置的方法及属性,这些可以叫做编程语言的接口:还有令我们既

python的自定义函数(函数类型、def、range、rerun)

一.PyCharm基本设置 1.用Ctrl+鼠标滚轮--放大或缩小字体 搜索zoom 2.在Windows资源管理器打开文件或目录 搜索keymap 设置成不常用的键即可,如F3. 3.代码提示 搜索letter 二.自定义函数 1.为什么要使用函数 函数中的代码一次编写,多处运行;函数可以让代码复用,减少代码冗余. 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print().但你也

typeScript入门(二)函数与类

3.ts的函数 1)函数的返回值和参数 在函数的定义需要定义其的返回值可以void,来表示没有返回值 函数参数的定义,举个例子分析下吧 name:string,age?:number=23 冒号后面是参数的类型,加个?表示这个参数不是必传的,所以你就可以在这理解到,这个?如果某个参数写了,那后面都是需要加的,因为它不是必传的.在类型后面用个赋值方式就是给这个参数写一个默认参数. 当参数很多的时候,你就用需要用三点运算符数组来接受参数. (...arr:any[]) 这样的话,都有的的参数都是存在

TypeScript入门-函数

▓▓▓▓▓▓ 大致介绍 TypeScript为JavaScript函数添加了额外的功能,让我们可以更容易地使用.TypeScript中的函数也包括JavaScript中最常见的两种函数 function add(x,y){ return x + y; } let add = function(x,y){ return x + y; } ▓▓▓▓▓▓ 函数类型 可以像变量一样为函数定义类型 function add(x: number, y: number): number { return x

TypeScript 函数-函数类型

//指定参数类型 function add(x:number,y:number){ console.log("x:"+x); // reutrn(x+y); } //指定函数类型 function add0(x:number,y:number):string{ // return((x+y).toString());//1 return((x+y)+"");//2 均可 } //匿名函数 let aa = function(x:number,y:string):st

TypeScript入门二:基本数据类型

浅析基本数据类型 TypeScript类型解析 一.浅析基本数据类型 首先有一个问题TypeScript是一门编译型语言?还是解释性语言?显然已经不能被这两个分类来区分,TypeScript的并不是为了让JavaScript改变执行方式,不是为了提高机器执行效率的.而编译型和解释型的分类是基于这两个特点的.但是,TypeScript具备编译型语言一个特点,就是它对类型进行检查,如果出现类型冲突时它是无法编译成js文件的. 既然TypeScript编译需要对变量进行类型检查,这就意味着TypeSc

TypeScript入门指南(JavaScript的超集)

TypeScript入门指南(JavaScript的超集) 你是否听过 TypeScript? TypeScript 是 JavaScript 的超集,TypeScript结合了类型检查和静态分析,显式接口.TypeScript是微软的开源项目,它是由C#之父Anders Hejlsberg发起的. 为什么会有 TypeScript? JavaScript 只是一个脚本语言,并非真正设计用于开发大型 Web 应用,JavaScript 没有提供类和模块等概念,对于一个真正的应用开发,TypeSc