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.函数重载

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

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

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

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

// 重载签名
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中的函数重载让我们定义以多种方式调用的函数。

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

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

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

到此这篇关于TypeScript中函数重载写法的文章就介绍到这了,更多相关TypeScript函数重载内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • TypeScript中的方法重载详解

    前言 方法重载(overload)在传统的静态类型语言中是很常见的.JavaScript 作为动态语言, 是没有重载这一说的.一是它的参数没有类型的区分,二是对参数个数也没有检查.虽然语言层面无法自动进行重载,但借助其动态的特性,我们可以在代码中手动检查入参的类型,或者通过 arguments 获取到参数个数,从而实现根据不同的入参做不同的操作. 比如有一个获取聊天消息的方法,根据传入的参数从数组中查找数据.如果入参为数字,则认为是 id,然后从数据源中找对应 id 的数据并返回,否则当成类型,

  • TypeScript中函数重载写法

    目录 1. 函数签名 2.函数重载 2.1 重载签名是可调用的 2.1 实现签名必须是通用的 3.方法重载 4. 何时使用函数重载 5.总结 前言: 大多数函数接受一组固定的参数.但有些函数可以接受可变数量的参数,不同类型的参数,甚至可以根据你调用函数的方式返回不同的类型.为了注释这样的函数,TypeScript 提供了函数重载功能. 1. 函数签名 我们先来考虑一个函数,它返回给一个特定的人的问候信息. function greet(person: string): string { retu

  • C++ 中函数重载、覆盖与隐藏详解

    C++ 中函数重载.覆盖与隐藏详解 在C++语言中,函数扮演着很重要的角色,不管面向过程设计,还是基于对象设计:不管是面向对象编程,还是基于泛型编程,函数都可以随处而见.在谈论C++中的函数重载.覆盖和隐藏之前,先回顾下函数的基础知识. 函数的声明包括函数的返回值类型,函数名称,参数列表(参数的类型.参数的个数.参数的顺序).例如,声明一个两个整数之和的函数,int iAdd(int iNum1,int iNum2);而函数的定义可以理解为对函数功能的详尽而准确的解说,通俗点,就是实现函数"ho

  • C++中函数重载实例详解

    C++中函数重载实例详解 函数重载: 1.具有相同的名称,执行基本相同的操作,但是使用不同的参数列表. 2.函数具有多态性. 3.编译器通过调用时参数的个数和类型确定调用重载函数的哪个定义. 4.只有对不同的数据集完成基本相同任务的函数才应重载. 函数重载的优 点 1.不必使用不同的函数名 2.有助于理解和调试代码 3.易于维护代码 接下来直接上代码: #include <iostream> using namespace std ; void say_hello(void) { cout &

  • javascript中函数的写法实例代码详解

    具体代码如下所述: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible

  • C++中函数重载详解

    目录 函数重载的概念 函数重载的应用 为什么C++支持函数重载,而C语言不支持 函数重载的概念 函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的 形参列表(参数个数 或 类型 或 顺序)必须不同,常用来处理实现功能类似数据类型不同的问题. 函数重载的应用 1.比如以下代码,函数名一样,而参数的类型不同,在调用的时候编译器会根据传递的参数自动进行匹配. 2.在例如以下代码,我们进行编译,都可以编译成功. 3.接下来看一个有趣的现象,将上述第二个例子

  • TypeScript 使用 Tuple Union 声明函数重载

    问题: TypeScript 中为函数添加多个签名后,依然需要添加相应的代码来判断并从不同的签名参数列表中获取对应的参数.过去常见的写法: function refEventEmitter(event?: string): void; function refEventEmitter(event: string, callback: () => void): void; function refEventEmitter(callback: () => void): void; function

  • 让JavaScript 轻松支持函数重载 (Part 1 - 设计)

    JavaScript支持重载吗? JavaScript支持函数重载吗?可以说不支持,也可以说支持.说不支持,是因为JavaScript不能好像其它原生支持函数重载的语言一样,直接写多个同名函数,让编译器来判断某个调用对应的是哪一个重载.说支持,是因为JavaScript函数对参数列表不作任何限制,可以在函数内部模拟对函数重载的支持. 实际上,在很多著名的开源库当中,我们都可以看到函数内部模拟重载支持的设计.例如说jQuery的jQuery.extend方法,就是通过参数类型判断出可选参数是否存在

  • TypeScript的函数定义与使用案例教程

    TypeScript中函数的定义和使用 1. 声明一个函数约束其传参类型,以及返回值类型 传入两个参数,没有返回值 const fun1 = (key: string, value: number): void => { console.log(key, value);//"Typescript",100 }; fun1("Typescript", 100); 2.TypeScript中的函数配置可选参数,在ES5或者ES6中函数中的实参可以不传递进去,但是在

  • TypeScript中的函数

    目录 1.函数定义 1.1JavaScript中的函数 1.2TypeScript中的函数 3.可选参数和默认参数 4.剩余参数 1.函数定义 1.1JavaScript中的函数 在学习TypeScript中的函数前我们先来回顾一下JavaScript中的函数定义常用的包含以下几种: 第一种:使用function关键字声明函数 function add1 (x, y) { return x + y } 第二种:使用字面量方式声明函数 const add2 = function (x, y) {

随机推荐