函数

定义函数

TypeScript支持两种定义函数方式,有名字的函数和匿名函数,和JavaScript相同:

// Named function
function add(x, y) {
    return x + y;
}
// Anonymous function
let myAdd = function(x, y) {
    return x + y;
};

函数参数类型定义和函数类型

函数类型包括完整的参数类型和返回值类型,下面例子中我们定义了一个函数对象变量myAdd,并立即将类型(x:number, y:number)=>number指定给它,然后使用function创建一个函数并赋值给myAdd

当然,针对下面例子,直观感觉这么写没什么必要,因为变量定义和函数对象定义写在一起,函数定义时已经指定一次参数类型和返回值类型了。对此我们不必担心,如果myAdd不写完整的函数类型,TypeScript编译器也能根据后面函数定义推断出正确的类型。

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

可选参数和默认参数

正常定义的每个函数参数都是必须的,不同于JavaScript。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
let result3 = buildName("Bob", "Adams");  // ah, just right

注意:可选参数必须放在后面。

参数默认值例子:

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
let result4 = buildName("Bob", "Adams");         // ah, just right

注意:

  • 可选参数和默认参数共享参数类型。
  • 带默认值的参数允许不放在所有普通参数后面,用户可以传入undefined获取默认值(和ES6相同),但最好不要这么干。

变长参数

JavaScript中通过arguments获得参数列表,TypeScript则是这样定义:

function buildName(firstName: string, ...restOfName: string[]) {
  return firstName + " " + restOfName.join(" ");
}
let buildNameFun: (fname: string, ...rest: string[]) => string = buildName;

this

this的值在函数被调用时才会指定,这在返回一个函数时会造成bug,详细请参考JavaScript精粹章节。TypeScript中有同样的用法。在EcmaScript6中,可以使用Lambda表达式(箭头函数),箭头函数不会覆盖this的值:

interface Card {
    suit: string;
    card: number;
}
interface Deck {
    suits: string[];
    cards: number[];
    createCardPicker(this: Deck): () => Card;
}
let deck: Deck = {
    suits: ["hearts", "spades", "clubs", "diamonds"],
    cards: Array(52),
    // NOTE: The function now explicitly specifies that its callee must be of type Deck
    createCardPicker: function(this: Deck) {
        return () => {
            let pickedCard = Math.floor(Math.random() * 52);
            let pickedSuit = Math.floor(pickedCard / 13);

            return {suit: this.suits[pickedSuit], card: pickedCard % 13};
        }
    }
}

注意:显式的this参数是为了避免this的类型为any。

重载

function pickCard(x: {suit: string; card: number; }[]): number;
function pickCard(x: number): {suit: string; card: number; };
function pickCard(x): 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 };
    }
}

注意:

  • 重载是按参数列表,从上到下匹配的。应该把精确定义放到前面。
  • function pickCard(x): any并不是重载的一部分。
作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。