Vue 3 中使用的函數重載有啥用?

你知道上圖中爲什麼定義了那麼多個 ref 函數,它們的作用是什麼?如果不清楚的話,閱讀完本文的內容,也許你就懂了。

這是一個簡單的 greet 函數,它接收一個字符串類型的參數,其返回值的類型也是字符串類型。

function greet(person: string): string {
  return `Hello, ${person}!`;
}

當使用字符串阿寶哥作爲參數調用 greet 函數時,將會返回 "Hello, 阿寶哥!"。那麼現在問題來了,如果我們希望 greet 函數能同時支持輸入用戶列表並返回相應的問候列表那該咋辦? 

給你 3 秒鐘的時間思考一下,你想到答案了麼?其中一種方案是使用聯合類型。

function greet(person: string | string[]): string | string[] {  
  if (typeof person === "string") {
    return `Hello, ${person}!`;
  } else if (Array.isArray(person)) {
    return person.map((name) =`Hello, ${name}!`);
  }
  throw new Error("Unable to greet");
}

而另一種解決方案是使用函數重載,使用函數重載技術,我們需要定義重載簽名和實現簽名。 

其中重載簽名定義了函數中每個參數的類型和函數的返回值類型,但不包含函數體。一個函數可以有多個重載簽名。 

而實現簽名的參數類型和返回值類型都需要使用更通用的類型,且還會包含實現該簽名的函數體。一個函數只能含有一個實現簽名。 

結合了重載簽名和實現簽名之後,我們就實現了前面所說的功能:

// 重載簽名
function greet(person: string): string;
function greet(persons: string[]): string[];
 
// 實現簽名
function greet(person: unknown): unknown {
  if (typeof person === 'string') {
    return `Hello, ${person}!`;
  } else if (Array.isArray(person)) {
    return person.map(name =`Hello, ${name}!`);
  }
  throw new Error('Unable to greet');
}

在實際使用的過程中,只有重載簽名纔是可以調用的,調用函數之後的返回值就能夠被推導出正確的類型。

需要注意的是,當 TypeScript 編譯器處理函數重載時,它會查找重載列表,嘗試使用第一個重載定義。如果匹配的話就立即返回。當使用實現簽名對應類型的參數調用實現簽名函數時將會出現錯誤。

除了重載普通函數之外,我們也可以對類中的方法進行重載。方法重載是指在同一個類中方法同名,參數不同(參數類型不同、參數個數不同或參數個數相同時參數的先後順序不同),調用時根據實參的形式,選擇與它匹配的方法執行操作的一種技術。

下面我們來看一個方法重載的例子:

class Calculator {
  add(a: number, b: number): number;
  add(a: string, b: string): string;
  add(a: string, b: number): string;
  add(a: number, b: string): string;
  add(a: string | number, b: string | number) {
  if (typeof a === 'string' || typeof b === 'string') {
    return a.toString() + b.toString();
  }
    return a + b;
  }
}

const calculator = new Calculator();
const result = calculator.add('Semlinker'' Kakuqo');

閱讀完本文之後,你應該就知道  Vue 3 響應式模塊中的 ref 函數背後使用了什麼技術。如果你還想進一步瞭解 TS 函數重載的相關知識,可以繼續閱讀 是時候表演真正的技術了 - TS 分身之術 這篇文章。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/kyOff_lCrKXWhyAamm-Prw