>  기사  >  웹 프론트엔드  >  TypeScript에서 함수 오버로딩을 작성하는 방법은 무엇입니까? 글쓰기 소개

TypeScript에서 함수 오버로딩을 작성하는 방법은 무엇입니까? 글쓰기 소개

青灯夜游
青灯夜游앞으로
2021-12-14 10:37:011933검색

TypeScript에서 함수 오버로딩을 작성하는 방법은 무엇입니까? 다음 글에서는 TypeScript에서 함수 오버로딩을 작성하는 방법을 소개하겠습니다. 도움이 되길 바랍니다.

TypeScript에서 함수 오버로딩을 작성하는 방법은 무엇입니까? 글쓰기 소개

대부분의 함수는 고정된 매개변수 세트를 허용합니다.

그러나 일부 함수는 다양한 수의 인수, 다양한 유형의 인수를 허용할 수 있으며 함수 호출 방법에 따라 다른 유형을 반환할 수도 있습니다. 이러한 함수에 주석을 달기 위해 TypeScript는 함수 오버로딩을 제공합니다.

1. 함수 시그니처

먼저 특정인에게 인사말을 반환하는 함수를 생각해보자.

function greet(person: string): string {
  return `Hello, ${person}!`;
}

위 함수는 사람 이름이라는 1개의 문자 유형 매개변수를 허용합니다. 이 함수를 호출하는 것은 매우 간단합니다.

greet('World'); // 'Hello, World!'

greet() 함수를 더 유연하게 만들고 싶다면 어떻게 해야 할까요? 예를 들어, 인사할 사람 목록을 추가로 허용하도록 합니다. 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.2 实现签名必须是通用的

// 重载签名
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()

이러한 함수는 문자열 또는 문자열 배열을 인수로 받아들이고 문자열 또는 문자열 배열을 반환합니다.

이러한 기능에 주석을 추가하는 방법은 무엇입니까? 두 가지 방법이 있습니다.

첫 번째 방법은 매우 간단합니다. 매개변수와 반환 유형을 업데이트하여 함수 시그니처를 직접 수정하는 것입니다. 다음은 리팩토링 후 greet()의 모습입니다.

const hi = new Greeter('Hi');
 
hi.greet('小智');       // 'Hi, 小智!'
hi.greet(['王大冶', '大冶']); // ['Hi, 王大冶!', 'Hi, 大冶!']

이제 두 가지 방법으로 greet()를 호출할 수 있습니다.

// 不推荐做法
function myFunc(): string;
function myFunc(param1: string): string;
function myFunc(param1: string, param2: string): string;
function myFunc(...args: string[]): string {
  // implementation...
}

지원하도록 함수 서명을 직접 업데이트합니다. multiple 이 호출 방법은 일반적이고 좋은 방법입니다.

그러나 경우에 따라 다른 접근 방식을 취하고 함수를 호출할 수 있는 모든 방법을 별도로 정의해야 할 수도 있습니다. 이 접근 방식을

함수 오버로딩이라고 합니다.

2. 함수 오버로딩

두 번째 방법은 함수 오버로딩 기능을 이용하는 것입니다. 함수 서명이 상대적으로 복잡하고 여러 유형이 포함될 때 이 접근 방식을 권장합니다.

함수 오버로드를 정의하려면 오버로드 서명과 구현 서명을 정의해야 합니다. 🎜🎜오버로드된 서명은 함수 본문 없이 함수의 형식 매개변수와 반환 유형을 정의합니다. 함수에는 함수를 호출하는 다양한 방법에 해당하는 여러 오버로드 서명이 있을 수 있습니다. 🎜🎜한편, 구현 시그니처에는 매개변수 유형과 반환 유형도 있고 구현 함수의 본문도 있으며 구현 시그니처는 하나만 있을 수 있습니다. 🎜
// 推荐做法
function myFunc(param1?: string, param2: string): string {
  // implementation...
}
🎜greet() 함수에는 두 개의 오버로드 서명과 하나의 구현 서명이 있습니다. 🎜🎜각 오버로드 서명은 함수를 호출할 수 있는 방법을 설명합니다. greet() 함수에 관한 한 문자열 매개변수 또는 문자열 배열 매개변수를 사용하여 두 가지 방법으로 호출할 수 있습니다. 🎜🎜구현 서명 function Greeting(person:known):known { ... }에는 함수 작동 방식에 대한 적절한 논리가 포함되어 있습니다. 🎜🎜이제 위와 같이 greet()를 문자열 유형 또는 문자열 배열의 인수로 호출할 수 있습니다. 🎜rrreee🎜🎜2.1 오버로드된 서명을 호출할 수 있습니다🎜🎜🎜구현 서명이 함수 동작을 구현하지만 직접 호출할 수는 없습니다. 오버로드된 서명만 호출 가능합니다. 🎜rrreee🎜위 예에서는 구현 서명이 알 수 없는 매개변수를 허용하더라도 greet( ) 함수를 사용합니다. 🎜🎜🎜2.2 구현 서명은 보편적이어야 합니다🎜🎜rrreee🎜오버로드 서명 함수 greet(person: string[]): string[] code>는 <code>greet(person:known): string과 호환되지 않는 것으로 표시됩니다. 🎜🎜부호 있는 string 반환 유형을 구현하는 것은 충분히 일반적이지 않으며 부호 있는 string[] 반환 유형을 오버로드하는 것과 호환되지 않습니다. 🎜🎜🎜3. 메소드 오버로딩🎜🎜🎜이전 예제에서는 일반 함수에 함수 오버로딩을 적용했습니다. 하지만 메서드를 오버로드할 수도 있습니다🎜🎜메서드 오버로드 간격에서 오버로딩 서명과 구현 서명은 클래스의 일부입니다. 🎜🎜예를 들어, 오버로드된 메소드 greet()를 사용하여 Greeter 클래스를 구현합니다. 🎜rrreee🎜🎜Greeter🎜 클래스에는 greet() 오버로드된 메서드가 포함되어 있습니다. 메서드 호출 방법을 설명하는 2개의 오버로드 서명과 올바른 구현을 포함하는 구현 서명🎜🎜메서드 오버로딩으로 인해 다음을 사용할 수 있습니다. hi.greet()를 호출하는 방법에는 문자열을 사용하거나 문자열 배열을 인수로 사용하는 두 가지 방법이 있습니다. 🎜rrreee🎜🎜4. 함수 오버로딩을 사용하는 경우🎜🎜🎜함수 오버로딩을 올바르게 사용하면 여러 가지 방법으로 호출할 수 있는 함수의 유용성이 크게 높아질 수 있습니다. 이는 자동 완성을 수행할 때 특히 유용합니다. 자동 완성에 가능한 모든 오버로드를 나열합니다. 🎜🎜그러나 어떤 경우에는 함수 오버로딩을 사용하지 않고 대신 함수 시그니처를 사용하는 것이 좋습니다. 🎜🎜 예를 들어, 선택적 매개변수에 함수 오버로딩을 사용하지 마세요: 🎜rrreee🎜 함수 시그니처에 선택적 매개변수를 사용하는 것으로 충분합니다: 🎜rrreee🎜🎜 5. 요약 🎜🎜🎜 TypeScript에서 함수 오버로딩 이쪽으로. 🎜🎜함수 오버로드를 사용하려면 오버로드 서명을 정의해야 합니다. 즉, 본문은 없지만 매개변수와 반환 유형이 있는 함수 집합입니다. 이러한 서명은 함수를 호출하는 방법을 나타냅니다. 🎜

또한 매개변수, 반환 유형, 함수 본문 등 함수의 올바른 구현(구현 서명)을 작성해야 합니다 . 구현 서명은 호출할 수 없습니다.

일반 함수 외에도 클래스의 메서드도 오버로드될 수 있습니다.

영어 원본 주소: https://dmitripavltin.com/typeript-function-overloading/

저자: dmitripavlutin

번역자: Front-end Xiaozhi

더 많은 프로그래밍 관련 지식을 보려면 다음을 방문하세요: 소개 프로그래밍 ! !

위 내용은 TypeScript에서 함수 오버로딩을 작성하는 방법은 무엇입니까? 글쓰기 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 segmentfault.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제