要理解 TypeScript 函式多載的概念,可以把它想像成生活中我們常見的「同一種行為有多種執行方式」的情境。
以下是一些日常例子,幫助你更直觀地理解這個技術:
點餐系統的應用:
order
函數有多種不同的參數組合和調用方式,這些多載的簽名就像不同的點餐方式,最終都是為了完成點餐這個任務。function order(dish: string): void // 口頭點餐
function order(dish: string, extras: string[]): void // 加點配料
function order(dish: string, callback: (confirmation: string) => void): void // 使用回呼函數
搜尋產品:
search
函數的多載簽名像是給搜尋行為添加不同的功能層次。function search(term: string): Promise<Product[]> // 簡單搜尋
function search(term: string, filters: string[]): Promise<Product[]> // 帶篩選條件
function search(term: string, callback: (products: Product[]) => void, filters?: string[]): void // 搜尋結果後觸發通知
約會提醒:
remind
函數可以根據不同參數組合以不同方式執行提醒。function remind(person: string, method: "message"): void // 發訊息
function remind(person: string, method: "calendar"): void // 日曆提醒
function remind(person: string, method: "email"): void // 寄電子郵件
**函式多載 Function Overloading ** 的核心是:同一個行為或操作,根據情況使用不同的「方式」來實現
,讓程式碼變得靈活且符合實際需求。
在 TypeScript 中,函式多載 (Function Overloading)
允許為函數定義多個簽名(signatures),每個簽名可以有不同的參數類型和返回類型。這在需要提供多種方式調用函數的情況下非常實用,同時還能保持類型安全。以下,我們將透過一個實際的例子探討函式多載的使用。
在以下程式碼中,我們有一個 search
函數,具有三個不同的多載簽名:
type Result = {
title: string,
url: string,
abstract: string
}
// 第一個多載:返回 Result 陣列的 Promise
function search(
term: string,
tags?: string[]
): Promise<Result[]>
// 第二個多載:接受回呼函數並返回 void
function search(
term: string,
callback: (results: Result[]) => void,
tags?: string[]
): void
// 實際實現,包含所有可能的參數組合
function search(
term: string,
p2?: string[] | ((results: Result[]) => void),
p3?: string[]
) {
// 判斷 p2 是否為回呼函數
const callback =
typeof p2 === 'function' ? p2 : undefined
// 判斷是否提供了 tags
const tags =
typeof p2 !== 'undefined' && Array.isArray(p2) ? p2 :
typeof p3 !== 'undefined' && Array.isArray(p3) ? p3 :
undefined;
let queryString = `?query=${term}`
if (tags && tags.length) {
queryString += `&tags=${tags.join()}`
}
// 向伺服器請求搜尋結果
const results = fetch(`/search${queryString}`)
.then(response => response.json())
// 如果有提供回呼函數則使用它,否則返回 Promise
if (callback) {
results.then(res => callback(res))
return
} else {
return results
}
}
函數簽名與載:
search
,並返回解析為 Result
陣列的 Promise
。search
,不返回任何值,而是直接透過回呼處理搜尋結果。實現細節:
p2
) 是回呼函數還是 tags 陣列。p2
是函數,則將其視為回呼;如果 p2
或 p3
是陣列,則視為 tags。根據參數執行不同邏輯:
search
將獲取結果並將其傳遞給回呼函數,而不返回任何東西,符合第二個多載的 void
返回類型。Promise
,符合第一個多載的 Promise<Result[]>
返回類型。返回 Promise:
search("TypeScript", ["programming", "language"])
.then(results => {
console.log(results);
});
使用回呼函數:
search("TypeScript", (results) => {
console.log(results);
}, ["programming", "language"]);
在這些範例中,你可以看到函式多載如何提供兩種不同的方式來使用 search
函數,取決於所需的行為。
TypeScript 的函式多載是程式碼世界的萬能膠!要發揮它的最大威力,以下幾點正確姿勢你一定要知道:
精準定義多載簽名:每個多載簽名都應該清楚地反映出不同的使用情境,避免讓人搞不清楚該用哪種方式調用函數。
避免濫用:雖然多載超好用,但也別為了多載而多載,確保每個多載都是真正需要的,避免讓程式碼變成難以維護的怪獸。
保持一致性:實現的函數體要能支持所有多載簽名,確保每種調用方式都能正常運行,不然會掉入意料之外的坑裡!
善用類型守衛:透過 TypeScript 的類型守衛來區分不同的參數組合,讓你的多載實現更清晰、更穩定。
加強可讀性與維護性:多載的目的是讓程式碼易讀、好維護,不要把邏輯寫得過於複雜,記住我們的目標是清楚簡潔!
正確使用 TypeScript 函式多載,可以讓你的程式碼靈活應對不同的需求,寫得更漂亮、更專業。
像我們的 search
函數一樣,輕鬆面對各種參數組合,實現更豐富的功能吧!٩(^ᴗ^)۶