1. 程式人生 > 程式設計 >TypeScript中函式過載寫法

TypeScript中函式過載寫法

目錄
  • 1. 函式簽名
  • 2.函式過載
    • 2.1 過載簽名是可呼叫的
    • 2.1 實現簽名必須是通用的
  • 3.方法過載
    • 4. 何時使用函式過載
      • 5.總結

        前言:

        大多數函式接受一組固定的引數。但有些函式可以接受可變數量的引數,不同型別的引數,甚至可以根據你呼叫函式的方式返回不同的型別。為了註釋這樣的函式,TypeScript 提供了函式過載功能。

        1. 函式簽名

        我們先來考慮一個函式,它返回給一個特定的人的問候資訊。

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

        上面的函式接受1個字元型別的引數:人的名字。呼叫該函式是非常簡單的:

        greet('World'); // 'Hello,World!'
        
        
        

        如果你想讓 greet()函式更加靈活,怎麼辦?例如,讓它另外接受一個要問候的人的列表。

        這樣的函式將接受一個字串或字串陣列作為引數,並返回一個字串或字串陣列。

        如何對這樣的函式進行註釋?有2種方法。

        第一種方法很簡單,就是通過更新引數和返回型別直接修改函式簽名。

        下面重構後greet()的樣子:

        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');
        }
        
        
        

        現在我們可以用兩種方式呼叫 greet():

        greet('World');          // 'Hello,World!'
        greet(['小智','大冶']); // ['Hello,小智!','Hello,大冶!']
        
        
        

        直接更新函式簽名以支援多種呼叫方式是一種常見的好方法。

        然而,在某些情況下,我們可能需要採用另一種方法,分別定義你的函式可以被呼叫的所有方式。這種方法被稱為函式過載。

        2.函式過載

        第二種方法是使用函式過載功能。當函式簽名相對複雜且涉及多種型別時,我推薦使用這種方法。

        定義函式過載需要定義過載簽名和一個實現簽名。

        過載簽名定義函式的形參和返回型別,沒有函式體。一個http://www.cppcns.com

        函式可以有多個過載簽名:對應於呼叫該函式的不同方式。

        另一方面,實現簽名還具有引數型別和返回型別,而且還有實現函式的主體,且只能有一個實現簽名。

        // 過載簽名
        function greet(person: string): string;
        function greet(persons: string[]): string[];
         
        // 實現簽名
        function greet(person: unknown): unknown {
          if (typeof person === 'string') {
            return `Hello,${name}!`);
          }
          thrTXJbHAsow new Error('Unable to greet');
        }
        
        
        

        greet() 函式有兩個過載簽名和一個實現簽名。

        每個過載簽名都描述了可以呼叫該函式的一種方式。就 greet()函式而言,我們可以用兩種方式呼叫它:用一個字串引數,或用一個字串陣列引數。

        實現簽名 function greet(person: unknown): unknown { ... } 包含了該函式如何工作的適當邏輯。

        現在,和上面一樣,可以用字串或字串陣列型別的引數來呼叫 greet()

        greet('World');          // 'Hello,大冶!']
        
        
        

        2.1 過載簽名是可呼叫的

        雖然實現簽名實現了函式行為,但是它不能直接呼叫。只有過載簽名是可呼叫的。

        greet('World');          // 過載簽名可呼叫
        greet(['小智','大冶']); // 過載簽名可呼叫
        
        const someValue: unknown = 'Unknown';
        greet(someValue);       // Implementation signature NOT callable
        
        // 報錯
        No overload matches this call.
          Overload 1 of 2,'(person: string): string',gave the following error.
            Argument of type 'unknown' is not assignable to parameter of type 'string'.
          Overload 2 of 2,'(persons: string[]): string[]',gave the following error.
            Argument of type 'unknown' is not assignable to parameter of type 'string[]'.
        
        

        在上面的示例中,即使實現簽名接受unknown引數,也不能使用型別為 unknown (greet(someValue)) 的引數呼叫 greet() 函式。

        2.1 實現簽名必須是通用的

        // 過載簽名
        function greet(person: string): string;
        function greet(persons: string[]): string[]; 
        // 此過載簽名與其實現簽名不相容。
        
         
        // 實現簽名
        function greet(person: unknown): string {
          // ...
          throw new Error('Unable to greet');
        }
        
        

        過載簽名函式 greet(person: string[]): string[] 被標記為與greet(person: unknown): string不相容。

        實現簽名的 string 返回型別不夠通用,不能與過載簽名的 string[] 返回型別相容。

        3.方法過載

        雖然在前面的例子中,函式過載被應用於一個普通函式。但是我們也可以過載一個方法

        在方法過載區間,過載簽名和實現簽名都是類的一部分了。

        例如,我們實現一個 Greeter類,有一個過載方法greet()

        class Greeter {
          message: string;
         
          constructor(message: string) {
            this.message = message;
          }
         
          // 過載簽名
          greet(person: string): string;
          greet(persons: string[]): string[];
         
          // 實現簽名
          greet(person: unknown): unknown {
            if (typeof person === 'string') {
              return `${this.message},${person}!`;
            } else if (Array.isArray(person)) {
              return person.map(name => `${this.message},${name}!`);
            }
            throw new Error('Unable to greet');
          }
        
        

        Greeter 類包含 greet() 過載方法: 2個過載簽名描述如何呼叫該方法,以及包含正確實現的實現簽名

        由於方法過載,我們可以用兩種方式呼叫 hi.greet():使用一個字串或使用一個字串陣列作為引數。

        const hi = new Greeter('Hi');
         
        hi.greet('小智');       // 'Hi,小智!'
        hi.greet(['王大冶','大冶']); // ['Hi,王大冶!','Hi,大冶!']
        
        
        

        4. 何時使用函式過載

        函式過載,如果使用得當,可以大大增加可能以多種方式呼叫的函式的可用性。這在自動補全時特別有用:我們會在自動補全中列出所有可能的過載記錄。

        然而,在某些情況下,建議不要使用函式過載,而應該使用函式簽名。

        例如,不要對可選引數使用函式過載:

        // 不推薦做法
        function myFunc(): string;
        function myFunc(param1: string): string;
        function myFunc(param1: string,param2: string): string;
        function myFunc(...args: string[]): string {
          // implementation...
        }
        
        
        

        在函式簽名中使用可選引數是足夠的:

        // 推薦做法
        function myFunc(param1?: string,param2: string): string {
          // implementation...
        }
        
        

        5.總結

        TypeScript中的函式過載讓我們定義以多種方式呼叫的函式。

        使用函式過載需要定義過載簽名:一組帶有引數和返回型別的函式,但沒有主體。http://www.cppcns.com這些簽名表明應該如何呼叫該函式。

        此外,你必須寫出函式的正確實現(實現簽名):引數和返回型別,以及函式體**。請注意,實現簽名是不可呼叫的。**

        除了常規的函式之外,類中的方法也可以過載。

        到此這篇關於TypeScript中函式過載寫法的文章就介紹到這了,更多相關TypeScript函式過載內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!