#yyds干货盘点#学会TypeScript中函数重载写法

Posted 尼羲

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了#yyds干货盘点#学会TypeScript中函数重载写法相关的知识,希望对你有一定的参考价值。

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

但有些函数可以接受可变数量的参数,不同类型的参数,甚至可以根据你调用函数的方式返回不同的类型。为了注释这样的函数,TypeScript 提供了函数重载功能。


函数签名

我们先来考虑一个函数,它返回给一个特定的人的问候信息。

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, 大冶!]

直接更新函数签名以支持多种调用方式是一种常见的好方法。

然而,在某些情况下,我们可能需要采用另一种方法,分别定义你的函数可以被调用的所有方式。这种方法被称为函数重载


函数重载

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

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

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

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

// 重载签名
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, 大冶!]
重载签名是可调用的

虽然实现签名实现了函数行为,但是它不能直接调用。只有重载签名是可调用的。

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()​ 函数。

实现签名必须是通用的
// 重载签名
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[]​​ 返回类型兼容。


方法重载

虽然在前面的例子中,函数重载被应用于一个普通函数。但是我们也可以重载一个方法

在方法重载区间,重载签名和实现签名都是类的一部分了。

例如,我们实现一个 ​​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, 大冶!]
何时使用函数重载

函数重载,如果使用得当,可以大大增加可能以多种方式调用的函数的可用性。这在自动补全时特别有用:我们会在自动补全中列出所有可能的重载记录。

然而,在某些情况下,建议不要使用函数重载,而应该使用函数签名。

例如,不要对可选参数使用函数重载:

// 不推荐做法
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...

总结

TypeScript中的函数重载让我们定义以多种方式调用的函数。

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

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

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

以上是关于#yyds干货盘点#学会TypeScript中函数重载写法的主要内容,如果未能解决你的问题,请参考以下文章

#yyds干货盘点# 系统学习 TypeScript——基础类型

#yyds干货盘点#面试官synchronized连环问,学会Monitor之后轻松拿下

#yyds干货盘点# 在120篇系列专栏中,才能学会 python beautifulsoup4 模块,7000字博客+爬第九工场网

#yyds干货盘点# 学python,怎么能不学习scrapy呢,这篇博客带你学会它

牛客最新前端笔试题解析 this指向题目解析及扩展 #yyds干货盘点#

#yyds干货盘点# C#中类的异常处理