大多数函数接受一组固定的参数。 但有些函数可以接受可变数量的参数,不同类型的参数,甚至可以根据你调用函数的方式返回不同的类型。为了注释这样的函数,TypeScript提供了函数重载功能。1。函数签名 我们先来考虑一个函数,它返回给一个特定的人的问候信息。functiongreet(person:string):string{returnHello,{person}!;} 上面的函数接受1个字符类型的参数:人的名字。调用该函数是非常简单的:greet(World);Hello,World! 如果你想让greet()函数更加灵活,怎么办?例如,让它另外接受一个要问候的人的列表。 这样的函数将接受一个字符串或字符串数组作为参数,并返回一个字符串或字符串数组。 如何对这样的函数进行注释?有2种方法。 第一种方法很简单,就是通过更新参数和返回类型直接修改函数签名。下面重构后greet()的样子:functiongreet(person:stringstring〔〕):stringstring〔〕{if(typeofpersonstring){returnHello,{person}!;}elseif(Array。isArray(person)){returnperson。map(nameHello,{name}!);}thrownewError(Unabletogreet);} 现在我们可以用两种方式调用greet():greet(World);Hello,World!greet(〔小智,大冶〕);〔Hello,小智!,Hello,大冶!〕 直接更新函数签名以支持多种调用方式是一种常见的好方法。 然而,在某些情况下,我们可能需要采用另一种方法,分别定义你的函数可以被调用的所有方式。这种方法被称为函数重载。2。函数重载 第二种方法是使用函数重载功能。当函数签名相对复杂且涉及多种类型时,我推荐使用这种方法。 定义函数重载需要定义重载签名和一个实现签名。 重载签名定义函数的形参和返回类型,没有函数体。一个函数可以有多个重载签名:对应于调用该函数的不同方式。 另一方面,实现签名还具有参数类型和返回类型,而且还有实现函数的主体,且只能有一个实现签名。重载签名functiongreet(person:string):functiongreet(persons:string〔〕):string〔〕;实现签名functiongreet(person:unknown):unknown{if(typeofpersonstring){returnHello,{person}!;}elseif(Array。isArray(person)){returnperson。map(nameHello,{name}!);}thrownewError(Unabletogreet);} greet()函数有两个重载签名和一个实现签名。 每个重载签名都描述了可以调用该函数的一种方式。就greet()函数而言,我们可以用两种方式调用它:用一个字符串参数,或用一个字符串数组参数。 实现签名functiongreet(person:unknown):unknown{。。。}包含了该函数如何工作的适当逻辑。 现在,和上面一样,可以用字符串或字符串数组类型的参数来调用greet()。greet(World);Hello,World!greet(〔小智,大冶〕);〔Hello,小智!,Hello,大冶!〕2。1重载签名是可调用的 虽然实现签名实现了函数行为,但是它不能直接调用。只有重载签名是可调用的。greet(World);重载签名可调用greet(〔小智,大冶〕);重载签名可调用constsomeValue:unknownUgreet(someValue);ImplementationsignatureNOTcallable报错Nooverloadmatchesthiscall。Overload1of2,(person:string):string,gavethefollowingerror。Argumentoftypeunknownisnotassignabletoparameteroftypestring。Overload2of2,(persons:string〔〕):string〔〕,gavethefollowingerror。Argumentoftypeunknownisnotassignabletoparameteroftypestring〔〕。 在上面的示例中,即使实现签名接受unknown参数,也不能使用类型为unknown(greet(someValue))的参数调用greet()函数。2。1实现签名必须是通用的重载签名functiongreet(person:string):functiongreet(persons:string〔〕):string〔〕;此重载签名与其实现签名不兼容。实现签名functiongreet(person:unknown):string{。。。thrownewError(Unabletogreet);} 重载签名函数greet(person:string〔〕):string〔〕被标记为与greet(person:unknown):string不兼容。 实现签名的string返回类型不够通用,不能与重载签名的string〔〕返回类型兼容。3。方法重载 虽然在前面的例子中,函数重载被应用于一个普通函数。但是我们也可以重载一个方法 在方法重载区间,重载签名和实现签名都是类的一部分了。 例如,我们实现一个Greeter类,有一个重载方法greet()。classGreeter{message:constructor(message:string){this。}重载签名greet(person:string):greet(persons:string〔〕):string〔〕;实现签名greet(person:unknown):unknown{if(typeofpersonstring){return{this。message},{person}!;}elseif(Array。isArray(person)){returnperson。map(name{this。message},{name}!);}thrownewError(Unabletogreet);} Greeter类包含greet()重载方法:2个重载签名描述如何调用该方法,以及包含正确实现的实现签名 由于方法重载,我们可以用两种方式调用hi。greet():使用一个字符串或使用一个字符串数组作为参数。consthinewGreeter(Hi);hi。greet(小智);Hi,小智!hi。greet(〔王大冶,大冶〕);〔Hi,王大冶!,Hi,大冶!〕4。何时使用函数重载 函数重载,如果使用得当,可以大大增加可能以多种方式调用的函数的可用性。这在自动补全时特别有用:我们会在自动补全中列出所有可能的重载记录。 然而,在某些情况下,建议不要使用函数重载,而应该使用函数签名。 例如,不要对可选参数使用函数重载:不推荐做法functionmyFunc():functionmyFunc(param1:string):functionmyFunc(param1:string,param2:string):functionmyFunc(。。。args:string〔〕):string{implementation。。。} 在函数签名中使用可选参数是足够的:推荐做法functionmyFunc(param1?:string,param2:string):string{implementation。。。}5。总结 TypeScript中的函数重载让我们定义以多种方式调用的函数。 使用函数重载需要定义重载签名:一组带有参数和返回类型的函数,但没有主体。这些签名表明应该如何调用该函数。 此外,你必须写出函数的正确实现(实现签名):参数和返回类型,以及函数体。请注意,实现签名是不可调用的。 除了常规的函数之外,类中的方法也可以重载。 作者:dmitripavlutin译者:前端小智来源:dmitripavlutin原文:https:dmitripavltin。comtyperiptfunctionoverloading