Function(函數分享)第二節

一、類型註解

1.1 類型註解

函數的類型註解分為兩個部分:參數類型註解和返回值類型註解。其中返回值類型註解有時候我們可以直接省略,因為Typescript可以根據返回的語句來自動判斷出返回值的類型。

function add (x: number, y: number): number { 
    return x + y;
} // 匿名函數完整的參數註解;
let myAdd: (x: number, y: number) => number = function(x: number, y: number): number { return x + y; }; // 匿名函數表達式完整的參數註解;
/*這其中,表達式左右的類型註解中,參數名稱可以不一致,我們需要把順序對應上即可。當函數沒有返回值的時候,我們用void類型進行註解。*/

當我們指定了賦值語句一側的類型之後,我們是可以忽略另一側的類型註解,在Typescript的類型推論中,被稱作「按上下文歸類」。

let myAdd = function(x: number, y: number): number {
  return x + y; 
}; //省略左側的類型註解
let myAdd: (baseValue: number, increment: number) => number = function(x, y) { return x + y; }; 
// 省略右側的類型註解,並且左右側的參數名稱並不相同。

除了基本的類型註解之外,我們還有其他的方式來描述這兩部分類型。
例如使用變數來單獨定義參數:

let param: { a: number };
function foo(param) {}

還可以利用介面的形式定義參數:

interface Param {
    a: number;
}
function foo (param: Param): number {
    return 1;
}

同時我們也可用這些方法去定義返回值的類型。
除此之外,我們還可以利用介面直接定義函數:

interface SearchFunc {
    (a: number, b: number): number;
}
let search : SearchFunc;
search = function(a: number, b: number) {
    return a+b;
}

1.2 可選參數和默認參數

在Typescript中定義函數是,定義了參數的個數及類型。當調用該函數時,必須嚴格遵守其個數和參數類型。但是在Javascript中,我們可以選擇性傳遞參數,當某個參數不傳值的時候,該參數的值為undefined。在TS中,我們可以使用?來表示該參數為可選參數。

let myAdd = function (a: number, b?: number) { //b為可選參數 
    if (b === undefined) { 
        return a;
    }
    return a + b;
}

除了使用可選參數之外,我們還可以給參數設置默認值:

let myAdd = function (a: number, b = 0) { //b不傳值時,該值為0
    return a + b
}

1.3 剩餘參數

當傳入的參數不確定數量時,可以使用…來表示剩餘參數,進行傳值。這與ES6中的用法是一致的。

function plus(firstNum: number, ...restofNum: number[]) {
    return firstNum + restofNum.reduce((a, b) => a + b);
} // 我們用一個數字類型的數組來規定剩餘參數的類型。
let a = plus(1, 2, 3, 4);
console.log(a); //10

二、函數重載

我們在JS中定義的函數,可以接受任意的參數,這裡的任意有兩層意義:一個是任意個數,一個是任意類型(JS中沒有類型檢查機制)。因此我們在構建一個健壯性足夠強的函數時,通常會用if語句或switch語句在其中進行類型或個數的判斷,來執行不同的邏輯。這在程式碼的意義上,也算是一種重載。但是其最大的問題在於,重載的邏輯是耦合在一起的,沒有做到邏輯分離。然而TS的重載,實際上也沒有很好的解決這個問題。

我們在聲明重載的時候需要注意以下幾點:

  • 重載函數只有函數聲明,沒有函數體。其本質是記錄你調用函數的方式。
  • 函數實現必須緊跟函數重載聲明。
  • 重載函數必須和其實現的參數個數保持一致,不能出現函數實現中不能滿足的重載聲明。
function padding(all: number); // 當傳入一個值的情況;
function padding(topAndBottom: number, leftAndRight: number) : {
    top: string;
    right: string;
    bottom: string;
    left: string;
}; //傳入兩個值的情況
function padding(top: number, right: number, bottom: number, left: number) : {
    top: number;
    right: number;
    bottom: number;
    left: number;
}; //傳入四個值的情況
function padding(a: number, b?: number, c?:number, d?:number) {
    if (b === undefined && c === undefined && d === undefined) { 
        b = c = d = a; 
    } else if (c === undefined && d === undefined) {
        c = a;
        d = b;
    }
    return {
        top: a,
        right: b,
        bottom: c,
        left: d,
    };
}
/*函數實現體內,通過if來處理不同參數情況的邏輯*/