作者:dmitripavlutin译者:前端小智来源:dmitripavlutin有梦想,有干货,微信搜索【大千世界】追踪这位凌晨还在洗碗的洗碗智慧。本文已收录到GitHubhttps://github.com/qq449245884/xiaozhi,里面有完整的测试站点、资料和我的一线厂商访谈系列文章。大多数函数接受一组固定的参数。但是有些函数可以接受可变数量的参数、不同类型的参数,甚至根据调用函数的方式返回不同的类型。为了注释此类函数,TypeScript提供了函数重载。1.函数签名让我们首先考虑一个向特定人返回问候消息的函数。functiongreet(person:string):string{return`Hello,${person}!`;}上面的函数接受1个字符类型的参数:人名。调用这个函数非常简单:greet('World');//'你好世界!'如果你想让greet()函数更灵活怎么办?例如,让它另外接受要问候的人员列表。这样的函数将接受一个字符串或字符串数??组作为参数,并返回一个字符串或字符串数??组。如何注释这样的功能?有2种方法。第一种方法很简单,就是通过更新参数和返回类型直接修改函数签名。这是重构后greet()的样子:functiongreet(person:string|string[]):string|string[]{if(typeofperson==='string'){return`你好,${person}!`;}elseif(Array.isArray(person)){returnperson.map(name=>`Hello,${name}!`);}thrownewError('Unabletogreet');}现在我们可以使用两种方式调用greet():greet('World');//'你好世界!'greet(['小智','大爷']);//['Hello,Xiaozhi!','Hello,Daye!']直接更新函数签名以支持多种调用方式是一种常用的好方法。然而,在某些情况下,我们可能需要采用另一种方法并单独定义函数的所有调用方式。这种方法称为函数重载。2.函数重载第二种方法是使用函数重载函数。当函数签名比较复杂并且涉及多种类型时,我推荐这种方法。定义函数重载需要定义重载签名和实现签名。重载签名定义函数的形式参数和返回类型,没有函数体。一个函数可以有多个重载签名:对应调用函数的不同方式。另一方面,实现签名也有参数类型和返回类型,还有实现函数体,而且只能有一个实现签名。//重载签名函数greet(person:string):string;functiongreet(persons:string[]):string[];//实现签名函数greet(person:unknown):unknown{if(typeofperson==='string'){return`Hello,${person}!`;}elseif(Array.isArray(person)){returnperson.map(name=>`Hello,${name}!`);}thrownewError('Unabletogreet');}greet()函数有两个重载签名和一个实现签名。每个重载签名都描述了调用函数的一种方式。就greet()函数而言,我们可以通过两种方式调用它:使用字符串参数,或使用字符串参数数组。实现签名函数greet(person:unknown):unknown{...}包含函数如何工作的适当逻辑。现在,如上所述,可以使用字符串类型或字符串数??组类型的参数调用greet()。问候('世界');//'你好世界!'greet(['小智','大友']);//['Hello,Xiaozhi!','Hello,Daye!']2.1重载签名是可调用的虽然实现签名实现了函数行为,但它不是直接可调用的。只有重载的签名是可调用的。问候('世界');//重载的签名可以调用greet(['Xiaozhi','Dayo']);//重载的签名可以调用constsomeValue:unknown='Unknown';greet(someValue);//实现签名不可调用//错误没有重载匹配此调用。重载1of2,'(person:string):string',出现以下错误。“未知”类型的参数不可分配给“字符串”类型的参数。重载2of2,'(persons:string[]):string[]',出现以下错误。“未知”类型的参数不可分配给“字符串[]”类型的参数。在上面的示例中,即使实现签名接受未知参数,也不能使用未知类型的参数(greet(someValue))调用greet()函数。2.1实现签名必须是通用的//重载签名函数greet(person:string):string;功能问候(人员:字符串[]):字符串[];//此重载签名与其实现签名不兼容。//实现签名函数greet(person:unknown):string{//...thrownewError('Unabletogreet');}重载签名函数greet(person:string[]):string[]ismarkedasIncompatible与问候(人:未知):字符串。实现签名的字符串返回类型不够通用,无法与重载签名的字符串[]返回类型兼容。3.方法重载虽然在前面的例子中,函数重载被应用到一个普通的函数上。但是我们也可以在方法重载范围内重载一个方法,重载签名和实现签名都是类的??一部分。例如,我们实现一个带有重载方法greet()的Greeter类。类Greeter{消息:字符串;构造函数(消息:字符串){this.message=message;}//重载签名greet(person:string):string;问候(人:字符串[]):字符串[];//实现签名greet(person:unknown):unknown{if(typeofperson==='string'){return`${this.message},${person}!`;}elseif(Array.isArray(person)){returnperson.map(name=>`${this.message},${name}!`);}thrownewError('无法打招呼');}Greeter类包含greet()重载方法:2重载签名描述了如何调用该方法,以及包含正确实现的实现签名由于方法重载,我们可以通过两种方式调用hi.greet():使用字符串或者以字符串数组作为参数。consthi=newGreeter('嗨');hi.greet('小智');//'嗨,小智!'hi.greet(['王大爷','大爷']);//['嗨,王大爷!','嗨,大爷!']4.何时使用函数重载函数重载如果使用得当,可以大大提高可能以多种方式调用的函数的可用性。这在自动完成期间特别有用:我们将在自动完成中列出所有可能的过载记录。但是,在某些情况下,建议不要使用函数重载,而是使用函数签名。例如,不要对可选参数使用函数重载://deprecatedfunctionmyFunc():string;functionmyFunc(param1:string):string;functionmyFunc(param1:string,param2:string):string;functionmyFunc(...args:string[]):string{//implementation...}在函数签名中使用可选参数就足够了//推荐做法functionmyFunc(param1?:string,param2:string):string{//implementation...}5.总结TypeScript中的函数重载让我们可以定义以多种方式调用的函数。使用函数重载需要定义一个重载签名:一组具有参数和返回类型但没有主体的函数。这些签名指示应如何调用该函数。此外,您还必须编写函数的正确实现(实现签名):参数和返回类型,以及函数体。请注意,实现签名不可调用。除了常规函数,类中的方法也可以被重载。代码部署后可能存在的bug,无法实时获知。事后为了解决这些bug,花费了大量的时间在日志调试上。顺便推荐一个好用的bug监控工具Fundebug。原文:https://dmitripavltin.com/typ...交流有梦想,有干货,微信搜索【伟大的走向世界】关注这位凌晨还在洗碗的洗碗智慧。本文GitHubhttps://github.com/qq44924588...已收录,有完整的测试站点、资料和我的一线厂商访谈系列文章。
