本网站(662p.com)打包出售,且带程序代码数据,662p.com域名,程序内核采用TP框架开发,需要联系扣扣:2360248666 /wx:lianweikj
精品域名一口价出售:1y1m.com(350元) ,6b7b.com(400元) , 5k5j.com(380元) , yayj.com(1800元), jiongzhun.com(1000元) , niuzen.com(2800元) , zennei.com(5000元)
需要联系扣扣:2360248666 /wx:lianweikj
TypeScript中函数重载写法,你在第几层!
吴振华 · 313浏览 · 发布于2021-12-13 +关注

TypeScript中的函数重载让我们定义以多种方式调用的函数。使用函数重载需要定义重载签名:一组带有参数和返回类型的函数,但没有主体。这些签名表明应该如何调用该函数。

大多数函数接受一组固定的参数。

但有些函数可以接受可变数量的参数,不同类型的参数,甚至可以根据你调用函数的方式返回不同的类型。为了注释这样的函数,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.函数重载

          第二种方法是使用函数重载功能。当函数签名相对复杂且涉及多种类型时,我推荐使用这种方法。

          定义函数重载需要定义重载签名和一个实现签名。

          重载签名定义函数的形参和返回类型,没有函数体。一个函数可以有多个重载签名:对应于调用该函数的不同方式。

          另一方面,实现签名还具有参数类型和返回类型,而且还有实现函数的主体,且只能有一个实现签名。

          // 重载签名 
          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'); 
          }

            greet() 函数有两个重载签名和一个实现签名。

            每个重载签名都描述了可以调用该函数的一种方式。就 greet()函数而言,我们可以用两种方式调用它:用一个字符串参数,或用一个字符串数组参数。

            实现签名 function greet(person: unknown): unknown { ... } 包含了该函数如何工作的适当逻辑。

            现在,和上面一样,可以用字符串或字符串数组类型的参数来调用 greet()。

            greet('World');          // 'Hello, World!' 
            greet(['小智', '大冶']); // ['Hello, 小智!', '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中的函数重载让我们定义以多种方式调用的函数。

                          使用函数重载需要定义重载签名:一组带有参数和返回类型的函数,但没有主体。这些签名表明应该如何调用该函数。

                          此外,你必须写出函数的正确实现(实现签名):参数和返回类型,以及函数体**。请注意,实现签名是不可调用的。**

                          除了常规的函数之外,类中的方法也可以重载。

                           


                          相关推荐

                          RN开发环境的npm私库本地debug调试

                          manongba · 688浏览 · 2019-05-09 17:03:46
                          你不知道的浏览器渲染原理

                          追忆似水年华 · 1362浏览 · 2019-05-09 22:47:56
                          基于iview的router常用控制方式

                          追忆似水年华 · 980浏览 · 2019-06-03 10:39:21
                          编程小知识之 JavaScript 文件读取

                          manongba · 708浏览 · 2019-06-10 09:16:16
                          10个省时间的 PyCharm 技巧 赶快收藏!

                          · 691浏览 · 2019-06-10 09:32:01
                          加载中

                          0评论

                          评论
                          坐标是江苏.南京,行业是互联网,技术是PHP和java,还有熟悉前后端等。
                          分类专栏
                          小鸟云服务器
                          扫码进入手机网页