関数について

基本的な関数

// 名前付き関数
function add(x: number, y: number): number {
    return x + y;
}
// 無名関数
let myAdd = function(x: number, y: number): number { return x + y; };

関数の型

type FuncType = (x: number, y: number) => number;

const func: FuncType = (x: number, y: number) : number => {
    return x + y;
};

console.log(func(1, 2)); // 3 を出力

任意引数とデフォルト引数

const getVolume = (horizontal: number, vertical = 5, height?: number): number => {
    return horizontal * vertical * ((height) ? height : 1);
}

console.log(getVolume(10, 10, 10)); // 1000 を出力
console.log(getVolume(10, 10)); // 100 を出力
console.log(getVolume(10)); // 50 を出力

Rest引数(Rest Parameters)

function buildNames(...restOfName: string[]) {
    return "(" + restOfName.join(" ") + ")";
}
console.log(buildNames("Baggio", "Zidane", "Totti", "Beckham")); // (Baggio Zidane Totti Beckham) を出力
console.log(buildNames()); // () を出力

必ず1件は指定させたいのであれば・・・

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

thisとアロー関数

下記をブラウザで実行するとthisには deckオブジェクトではなくwindowが設定されてしまうためエラーとなる

let deck = {
    suits: ["hearts", "spades", "clubs", "diamonds"],
    cards: Array(52),
    createCardPicker: function() {
        return function() {
            let pickedCard = Math.floor(Math.random() * 52);
            let pickedSuit = Math.floor(pickedCard / 13);
            return {suit: this.suits[pickedSuit], card: (pickedCard % 13) + 1};
        }
    }
}
let cardPicker = deck.createCardPicker();
let pickedCard = cardPicker();
console.log("card: " + pickedCard.card + " of " + pickedCard.suit);

アロー関数は、関数が実行された場所ではなく、関数が作られた場所でthisを捕捉する為、thisはdeckオブジェクトを参照するようになる。

let deck = {
    suits: ["hearts", "spades", "clubs", "diamonds"],
    cards: Array(52),
    createCardPicker: function() {
        // アロー関数に変更
        return () => {
            let pickedCard = Math.floor(Math.random() * 52);
            let pickedSuit = Math.floor(pickedCard / 13);
            return {suit: this.suits[pickedSuit], card: (pickedCard % 13) + 1};
        }
    }
}
let cardPicker = deck.createCardPicker();
let pickedCard = cardPicker();
console.log("card: " + pickedCard.card + " of " + pickedCard.suit);
thisパラメーター

ただ、上記の場合、--noImplicitThisフラグをコンパイラに渡している場合、this.suits[pickedSuit]のthisがany型であることが指摘されてしまうらしい。これを解消する為には次のthisパラメータを使用する。

noImplicitThis・・・thisの型が暗黙的にanyになる場合、エラーが出るようになる

function f(this: void) {
    // thisを明確にする為、第1引数にthisを指定する
    // この関数を呼び出す際にこの第1引数を指定することはない
    // もし関数に引数を渡したい場合は第2引数以降に定義する
}
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) + 1};
        }
    }
}
// createCardPickerに引数を指定しなくてもコンパイルエラーにならない
let cardPicker = deck.createCardPicker();
let pickedCard = cardPicker();
console.log("card: " + pickedCard.card + " of " + pickedCard.suit);