为函数定义类型

  1. let myAdd = function(x: number, y: number): number { return x + y; };
  2. //myAdd 是一个函数类型,有两个参数分别是x,y并且都为数值类型,返回值也是数值类型

书写完整的函数类型

  1. let myAdd: (x: number, y: number) => number =
  2. function(x: number, y: number): number { return x + y; };
  3. //myAdd 是一个函数类型,有两个参数分别是x,y并且都为数值类型,返回值也是数值类型
  4. 这是一个完整的类型

函数类型包含两部分,参数类型和返回值类型。只要参数类型匹配,并不在乎参数名是否一致,返回类型也不许和声明的类型一致。

推断类型:在typescript中 ,编译器会自动识别类型(按上下文归类,是类型推论的一种)

可选参数和默认参数

  1. function buildName(firstName: string, lastName?: string) {
  2. if (lastName)
  3. return firstName + " " + lastName;
  4. else
  5. return firstName;
  6. }
  7. let result1 = buildName("Bob"); // works correctly now
  8. let result2 = buildName("Bob", "Adams", "Sr."); // error, too many parameters
  9. let result3 = buildName("Bob", "Adams"); // ah, just right
  10. buildName有两个参数firstName字符串类型必传,lastName属性后有一个?代表是可选类型,可以不传,如果传递必须是字符串类型,另外可选参数必须在必须参数后面。并且可以设置参数的默认值;'
  11. function buildName(firstName: string ='aaa', lastName?: string) {
  12. if (lastName)
  13. return firstName + " " + lastName;
  14. else
  15. return firstName;
  16. }

在所有必须参数后面带默认初始化的参数都是可选的,可以省略不全,也就是说可选参数与末尾的默认参数共享参数类型。

  1. function buildName(firstName: string, lastName?: string) {} 等同于
  2. function buildName(firstName: string, lastName = "Smith") {}

如果带默认值的参数放在必须参数值的前面,则函数要明确的传入undefined值来获得默认值。

  1. function buildName(firstName = "Will", lastName: string) {
  2. return firstName + " " + lastName;
  3. }
  4. let result4 = buildName(undefined, "Adams"); //error

剩余参数

必须参数,默认参数,可选参数都有共同点,他表示一个参数,如果你不知道后边有多少个参数可以利用剩余参数来实现

  1. function buildName(firstName: string, ...restOfName: string[]) {
  2. return firstName + " " + restOfName.join(" ");
  3. }
  4. let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");
  5. buildName函数第一个参数为string,第二个参数利用剩余参数,转化为数组,

this和箭头函数

普通函数在运行时才知道this指向,使用箭头函数,在函数被返回时就绑好正确的this

  1. let deck = {
  2. suits: ["hearts", "spades", "clubs", "diamonds"],
  3. cards: Array(52),
  4. createCardPicker: function() {
  5. // NOTE: the line below is now an arrow function, allowing us to capture 'this' right here
  6. return () => {
  7. let pickedCard = Math.floor(Math.random() * 52);
  8. let pickedSuit = Math.floor(pickedCard / 13);
  9. return {suit: this.suits[pickedSuit], card: pickedCard % 13};
  10. }
  11. }
  12. }
  13. let cardPicker = deck.createCardPicker();
  14. let pickedCard = cardPicker();
  15. alert("card: " + pickedCard.card + " of " + pickedCard.suit);

注意:如果createCardPicker返回的是一个普通函数,且 编译器做了 noImplicitThis 值为true 是,会提示this 类型为any

  1. let deck = {
  2. suits: ["hearts", "spades", "clubs", "diamonds"],
  3. cards: Array(52),
  4. createCardPicker: function() {
  5. // NOTE: the line below is now an arrow function, allowing us to capture 'this' right here
  6. return function() {
  7. let pickedCard = Math.floor(Math.random() * 52);
  8. let pickedSuit = Math.floor(pickedCard / 13);
  9. return {suit: this.suits[pickedSuit], card: pickedCard % 13};
  10. }
  11. }
  12. }
  13. let cardPicker = deck.createCardPicker();
  14. let pickedCard = cardPicker();
  15. // this.suits[pickedSuit] 报错显示this 是一个any类型。

this参数

不幸的是,this.suits[pickedSuit]的类型依旧为any。 这是因为 this来自对象字面量里的函数表达式。 修改的方法是,提供一个显式的 this参数。 this参数是个假的参数,它出现在参数列表的最前面:

  1. function f(this: void) {
  2. }

所以上面的例子可以这样改

  1. let deck = {
  2. suits: ["hearts", "spades", "clubs", "diamonds"],
  3. cards: Array(52),
  4. createCardPicker: function(this: Deck) { //此处显示的指出了this指向为Deck,也可以不写类型自动推导
  5. // NOTE: the line below is now an arrow function, allowing us to capture 'this' right here
  6. return () => {
  7. let pickedCard = Math.floor(Math.random() * 52);
  8. let pickedSuit = Math.floor(pickedCard / 13);
  9. return {suit: this.suits[pickedSuit], card: pickedCard % 13};
  10. }
  11. }
  12. }
  13. let cardPicker = deck.createCardPicker();
  14. let pickedCard = cardPicker();
  15. alert("card: " + pickedCard.card + " of " + pickedCard.suit);
  16. 也可以将deck.createCardPicker的返回函数修改为如下:
  17. return function(this:Deck) { 返回普通函数,显示指向this
  18. let pickedCard = Math.floor(Math.random() * 52);
  19. let pickedSuit = Math.floor(pickedCard / 13);
  20. return { suit: this.suits[pickedSuit], card: pickedCard % 13 };
  21. }

this参数在回调函数里

当一个函数传递到另一个函数被调用时,他们会当成一个普通函数,this为undefined。我们稍作改动通过this函数避免错误,首先要指定this类型

  1. interface UIElement {
  2. addClickListener(onclick: (this: void, e: Event) => void): void;
  3. }
  4. thisvoid 表示addClickListener期望onclick 是一个不需要此类型得函数

下面为调用代码

  1. interface UIElement {
  2. addClickListener(onclick: (this: void, e: Error) => void): void;
  3. }
  4. class Handler {
  5. info: string = '';
  6. onClickBad(this: Handler, e: Error) {
  7. // oops, used this here. using this callback would crash at runtime
  8. this.info = e.message;
  9. }
  10. }
  11. let h = new Handler();
  12. let uiElement: UIElement = {
  13. addClickListener: (onclick: (this: void, e: Error) => void): void => {
  14. // do something
  15. }
  16. }
  17. uiElement.addClickListener(h.onClickBad); // error! onClickBad指定this 必须在Handler类中使用

当我们指定this类型时候,显示声明得onClickBad就必须在Hadnler,这是因为typescript会检测到指定类型
我们下面添加另一个方法让this为void

  1. interface UIElement {
  2. addClickListener(onclick: (this: void, e: Error) => void): void;
  3. }
  4. class Handler {
  5. info: string = '';
  6. onClickBad(this: Handler, e: Error) {
  7. // oops, used this here. using this callback would crash at runtime
  8. this.info = e.message;
  9. }
  10. onClickGood(this: void, e: Error){
  11. this.info = e.message; //error thsi 指向问题
  12. }
  13. }
  14. let h = new Handler();
  15. let uiElement: UIElement = {
  16. addClickListener: (onclick: (this: void, e: Error) => void): void => {
  17. // do something
  18. }
  19. }
  20. uiElement.addClickListener(h.onClickBad); // error! onClickBad指定this 必须在Handler类中使用
  21. uiElement.addClickListener(h.onClickGood); // ok!

但是,this.info就不可用了因为它不指向Hander,如果都需要那么将onClickGood改成箭头函数即可。因为箭头函数不会捕获this,所以我们总是可以把他们传给期望得this:void 函数,缺点就是每个Handler 对象都会创建一个箭头函数,另一方面,方法只会被创建一次,添加到 Handler的原型链上。 它们在不同 Handler对象间是共享的。

  1. class Handler {
  2. info: string = '';
  3. onClickBad(this: Handler, e: Error) {
  4. // oops, used this here. using this callback would crash at runtime
  5. this.info = e.message;
  6. }
  7. onClickGood = (e: Error) => {
  8. this.info = e.message; //不报错
  9. }
  10. }
  11. let h = new Handler();
  12. let uiElement: UIElement = {
  13. addClickListener: (onclick: (this: void, e: Error) => void): void => {
  14. // do something
  15. }
  16. }
  17. uiElement.addClickListener(h.onClickGood); //ok

重载:方法名相同但是参数和返回值不同

方法是为同一个函数提供多个函数类型定义来进行函数重载。传入不同参数就会得到不同的值。 编译器会根据这个列表去处理函数的调用。为了让编译器能够正确的检查类型,在查找列表的时候,一定要把最精确得定义放在最前面

  1. let suits = ["hearts", "spades", "clubs", "diamonds"];
  2. function pickCard(x: {suit: string; card: number; }[]): number;
  3. function pickCard(x: number): {suit: string; card: number; };
  4. function pickCard(x): any {
  5. // Check to see if we're working with an object/array
  6. // if so, they gave us the deck and we'll pick the card
  7. if (typeof x == "object") {
  8. let pickedCard = Math.floor(Math.random() * x.length);
  9. return pickedCard;
  10. }
  11. // Otherwise just let them pick the card
  12. else if (typeof x == "number") {
  13. let pickedSuit = Math.floor(x / 13);
  14. return { suit: suits[pickedSuit], card: x % 13 };
  15. }
  16. }
  17. let myDeck = [{ suit: "diamonds", card: 2 }, { suit: "spades", card: 10 }, { suit: "hearts", card: 4 }];
  18. let pickedCard1 = myDeck[pickCard(myDeck)];
  19. console.log("card: " + pickedCard1.card + " of " + pickedCard1.suit);
  20. let pickedCard2 = pickCard(15);
  21. console.log("card: " + pickedCard2.card + " of " + pickedCard2.suit);

注意:function pickCard(x):any 并不是重载列表的一部分,这里有两个重载,一个接收对象,另一个接收数字,以其他参数调用会产生错误。

知识总结:

  1. 1.TypeScript中可以为函数定义类型
  2. let myadd:(x:number,y:number)=>number = (x:number,y:number):number {
  3. return x + y;
  4. }
  5. 其中 (x:number,y:number)=>number 这就是为函数定义的的类型,只需要参数类型匹配即可
  6. 2.TypeScript编译器中,编译器会自动识别出类型,这叫做按上下文归类,是类型推论中得一种
  7. 3.TypeScript参数有可选和默认参数,如果定义得函数中某个参数是可选的(也就是可以不传递),默认参数也可以不传递,但是必须占位,并且可选参数一定要在必传参数得后面.
  8. function buildName(firstName: string, lastName?: string) {
  9. return firstName + " " + lastName;
  10. }
  11. lastName后面跟一个?就代表是可选包参数
  12. function buildName(firstName: string, lastName = "Smith") {
  13. return firstName + " " + lastName;
  14. }
  15. lastName = "Smith" 是默认参数,他也是可选得。
  16. 4.剩余参数,如果函数得参数不固定可以用 "...arg" 将他们变成一个数组
  17. 5.this 参数 我们可以显示得指出this 他是一个假参数,只是告诉编译器this需要在什么地方能够使用,有时候this可能是一个any类型,如果你给编译器设置了--noImplicitThis标记。 它会指出 否个函数里的this的类型为any
  18. 6.重载:是为一个函数提供多个函数类型定义。另外只是类型重载,并不是函数重载,比如上面的例子,是两个重载而不是三个