接續 第 8 天的 - Function
今天來談談一個在 JavaSceipt 中沒有,在 TypeScript 中卻有的概念 - Function Overloads(函式重載)
你會了解到「Function Overloads 是什麼」、它想要解決什麼問題以及實作時我們該注意什麼
Function Overloads 中文可以翻成「函式重載」、「函式過載」
不過在談 函式重載(Function Overloads) 之前,先來談談 函式簽名(Function Signatures )
他們有著緊密的關係
第一次看到這個專有名詞時整個霧颯颯@@ 想說這是什麼
「函式簽名」通常由函式的名稱
、參數組合
,以及回傳值的型別
所組成,就像是一個集合體,裡面放了函式的相關資訊。它幫我們確定了在調用函式時的預期方式以及需要傳入的參數數量和型別
JavaScript 本身是一個動態語言,它並不像強型別語言(如:C#)中有「函式簽名」的概念
但在 TypeScript 中,「函式簽名」變得非常重要!
在不同的語言裡,「函式簽名」的定義和細節略有不同,但以 TypeScript 為例,包含以下幾個部分:
函式名稱
參數組合:包含數量、型別和順序
回傳值型別
function add(a: number, b: number): number {
return a + b;
}
以上方這例子來說
add
(a: number, b: number)
number
In TypeScript, we can specify a function that can be called in different ways by writing overload signatures. To do this, write some number of function signatures (usually two or more), followed by the body of the function
節錄自官方文件
上方的文字主要是在說,每一個簽名都定義了一種可能的參數列表,函式在重載時,利用簽章的不同來區分到底是呼叫了哪個方法。 Function Overloads 允許同一個函式名稱具有多個不同的函式簽名(通常是 2 個以上),這也代表眼前的某個函式,可以根據不同數量、型別的參數來執行不同的行為
函式重載(Function Overloads) 可以分為兩大部分:
// 重載簽名 overload signatures
function greet(name: string): string;
function greet(age: number): string;
// 實施簽名 Implementation Signature
function greet(value: any): string {
if (typeof value === "string") {
return `Hello ${value}!`;
} else if (typeof value === "number") {
return `You are ${value} years old.`;
}
return;
}
console.log(greet("Alice")); // Hello Alice!
console.log(greet(25)); // You are 25 years old.
可以看到滑鼠游標放到函式名稱上會出現 +1 overloads
的提示字樣,這是在告訴你還有另外 1 個 function overloads
// 沒有重載的情況
function printNumber(num: number) {
console.log(num);
}
function printString(str: string) {
console.log(str);
}
// 沒有重載的情況
function process(value: string | number) {
if (typeof value === 'string') {
console.log(`String: ${value}`);
} else {
console.log(`Number: ${value}`);
}
}
假設我們正在寫一個用於計算商品的價格的函式,它需要根據不同情況提供不同的計算方式和結果:
如果不用函式重載,這個函式的邏輯甚至長相可能會變得更複雜,因為會需要處理多個可選參數
// 沒有重載的情況
function calculatePrice(item: string, quantity?: number, discountCode?: string): number {
let price = 100; // 預設價格
if (quantity) {
price *= quantity; // 總價
}
if (discountCode) {
price *= 0.9; // 折扣碼統一打九折
}
return price;
}
calculatePrice("Laptop"); // 100
calculatePrice("Laptop", 2); // 200
calculatePrice("Laptop", 2, "2024HappyHour"); // 180
❌ Don't ❌
function print(value: number): void;
function print(value: string): void;
function print(value: boolean): void;
function print(value: null): void; // 過度重載
function test(x: number, y: number): void;
function test(x: number, y: number, z: number): void; // 這兩個簽名過於相似
✅ Do's ✅
function getUserInfo(id: number): User;
function getUserInfo(email: string): User;
function processOrder(id: number): void;
function processOrder(name: string): void;
function setStatus(status: 'active' | 'inactive' | 'pending'): void;
我在寫這篇文章時,心中有冒出一個疑問~
Q: 重載 不是也是寫了很多重複的 code 嗎?
A: 重載確實會在定義多個簽名時產生重複的 code。但這些簽名本身並不包含邏輯,而是提供了編譯器型別檢查的一個判斷依據,真正的邏輯只需要在「實施簽名(Implementation Signature)」中實現一次就好
這樣雖然看起來是多次聲明,但重載實際上減少了在實際程式碼中的重複邏輯
函式簽名
定義了函式的「參數型別」、「數量」、「回傳型別」等,這是函式重載的判斷基礎Function Overloads (函式重載)
允許同一個函式根據不同簽名接受不同類型或數量的參數每天講的內容有推到 github 上喔