TypeScript – Functions(函数类型)

时间:2021-1-8 作者:admin

函数中的类型注解

函数可以指定每个参数和返回值的类型:

function add(x: number, y: number): number {
  return x + y;
}

let myAdd = function (x: number, y: number): number {
  return x + y;
};

当省略返回值的类型注解,Typescript 会自动根据返回的值进行类型推断。

函数类型

像其他变量的注解一样,也可以对一个变量标注为函数类型,格式为 (a: number, b:number) => number, 如下:

let myAdd: (x: number, y: number) => number = function (
  x: number,
  y: number
): number {
  return x + y;
};

注意 xy 只是提供占位功能,可以任意取名

类型推断

可以只写等式一边的类型注解,其余一边 Typescript 会自动根据语言环境自动进行类型推断:

// The parameters 'x' and 'y' have the type number
let myAdd = function (x: number, y: number): number {
  return x + y;
};

// myAdd has the full function type
let myAdd2: (baseValue: number, increment: number) => number = function (x, y) {
  return x + y;
};

可选和默认参数

Typescript 中函数的参数默认是都是必须的,所以在函数调用时传递参数的数量必须和声明时要相同:

function buildName(firstName: string, lastName: string) {
  return firstName + " " + lastName;
}

let result1 = buildName("Bob"); // error, too few parameters
Expected 2 arguments, but got 1.
let result2 = buildName("Bob", "Adams", "Sr."); // error, too many parameters
Expected 2 arguments, but got 3.
let result3 = buildName("Bob", "Adams"); // ah, just right

JavaScript 中,函数的每个参数都是可选的,用户可以根据情况传递,没有传参的值默认为 undefined。而在 TypeScript 中,要想让一个参数可选,可以把类型注解改为 ?:

function buildName(firstName: string, lastName?: string) {
  if (lastName) return firstName + " " + lastName;
  else return firstName;
}

let result1 = buildName("Bob"); // works correctly now
let result2 = buildName("Bob", "Adams", "Sr."); // error, too many parameters
Expected 1-2 arguments, but got 3.
let result3 = buildName("Bob", "Adams"); // ah, just right

注意的是,可选参数需要跟在必录参数后面。另外,我们可以为一个参数提供默认值,在用户没传或者传 undefined 使用它:

function buildName(firstName: string, lastName = "Smith") {
  return firstName + " " + lastName;
}

let result1 = buildName("Bob"); // works correctly now, returns "Bob Smith"
let result2 = buildName("Bob", undefined); // still works, also returns "Bob Smith"
let result3 = buildName("Bob", "Adams", "Sr."); // error, too many parameters
Expected 1-2 arguments, but got 3.
let result4 = buildName("Bob", "Adams"); // ah, just right

跟随在必录参数后面的可选参数和默认参数可以看成是等价的:

function buildName(firstName: string, lastName?: string) {
  // ...
}

等于:

function buildName(firstName: string, lastName = "Smith") {
  // ...
}

和可选参数不一样的是,默认参数可以在必录参数前面出现。这个时候需要使用默认值,必须显示传递 undefiend 值:

function buildName(firstName = "Will", lastName: string) {
  return firstName + " " + lastName;
}

let result1 = buildName("Bob"); // error, too few parameters
Expected 2 arguments, but got 1.
let result2 = buildName("Bob", "Adams", "Sr."); // error, too many parameters
Expected 2 arguments, but got 3.
let result3 = buildName("Bob", "Adams"); // okay and returns "Bob Adams"
let result4 = buildName(undefined, "Adams"); // okay and returns "Will Adams"

剩余参数

ES6 中的剩余参数类似,用 ... 表示剩余参数,它可以看出把所有的可选参数都放进一个数组:

function buildName(firstName: string, ...restOfName: string[]) {
  return firstName + " " + restOfName.join(" ");
}

// employeeName will be "Joseph Samuel Lucas MacKinzie"
let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");

同时支持函数类型注解和声明:

function buildName(firstName: string, ...restOfName: string[]) {
  return firstName + " " + restOfName.join(" ");
}

let buildNameFun: (fname: string, ...rest: string[]) => string = buildName;

函数重载

有一些函数的参数类型可以是多种类型的,并且返回类型也可以是不确定的:

let suits = ["hearts", "spades", "clubs", "diamonds"];

function pickCard(x: any): any {
  // Check to see if we're working with an object/array
  // if so, they gave us the deck and we'll pick the card
  if (typeof x == "object") {
    let pickedCard = Math.floor(Math.random() * x.length);
    return pickedCard;
  }
  // Otherwise just let them pick the card
  else if (typeof x == "number") {
    let pickedSuit = Math.floor(x / 13);
    return { suit: suits[pickedSuit], card: x % 13 };
  }
}

let myDeck = [
  { suit: "diamonds", card: 2 },
  { suit: "spades", card: 10 },
  { suit: "hearts", card: 4 },
];

let pickedCard1 = myDeck[pickCard(myDeck)];
alert("card: " + pickedCard1.card + " of " + pickedCard1.suit);

let pickedCard2 = pickCard(15);
alert("card: " + pickedCard2.card + " of " + pickedCard2.suit);

上面函数如果传入一个对象,则返回一个 number。如果传入一个数字,则返回卡片对象。那在 TypeScript 中如何准确的描述这些不同参数的类型呢?那就是函数重载,它允许我们定义一系列不同情况的参数类型注解,并且一般遵循从具体到最模糊的顺序进行声明:

let suits = ["hearts", "spades", "clubs", "diamonds"];

function pickCard(x: { suit: string; card: number }[]): number;
function pickCard(x: number): { suit: string; card: number };
function pickCard(x: any): any {
  // Check to see if we're working with an object/array
  // if so, they gave us the deck and we'll pick the card
  if (typeof x == "object") {
    let pickedCard = Math.floor(Math.random() * x.length);
    return pickedCard;
  }
  // Otherwise just let them pick the card
  else if (typeof x == "number") {
    let pickedSuit = Math.floor(x / 13);
    return { suit: suits[pickedSuit], card: x % 13 };
  }
}

let myDeck = [
  { suit: "diamonds", card: 2 },
  { suit: "spades", card: 10 },
  { suit: "hearts", card: 4 },
];

let pickedCard1 = myDeck[pickCard(myDeck)];
alert("card: " + pickedCard1.card + " of " + pickedCard1.suit);

let pickedCard2 = pickCard(15);
alert("card: " + pickedCard2.card + " of " + pickedCard2.suit);

在函数调用时, TypeScript 会从重载函数列表第一个开始进行类型匹配,如果参数匹配成功,就会根据这个声明进行类型检查。

注意的是,函数重载列表最后一个声明不会进行类型匹配,所以上面的列表如果参数不匹配前面2钟话,就会抛出异常

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。