ホームページ  >  記事  >  ウェブフロントエンド  >  TypeScriptで関数のオーバーロードを記述するにはどうすればよいですか?ライティングの紹介

TypeScriptで関数のオーバーロードを記述するにはどうすればよいですか?ライティングの紹介

青灯夜游
青灯夜游転載
2021-12-14 10:37:011990ブラウズ

TypeScript で関数のオーバーロードを記述するにはどうすればよいですか? TypeScriptで関数のオーバーロードを記述する方法については、次の記事で紹介していますので、ご参考になれば幸いです。

TypeScriptで関数のオーバーロードを記述するにはどうすればよいですか?ライティングの紹介

ほとんどの関数は、固定されたパラメータのセットを受け入れます。

ただし、一部の関数は、可変数のパラメーターやさまざまなタイプのパラメーターを受け入れ、関数の呼び出し方法に応じてさまざまなタイプを返すこともできます。このような関数に注釈を付けるために、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() を 2 つの方法で呼び出すことができます:

greet('World');          // 'Hello, World!'
greet(['小智', '大冶']); // ['Hello, 小智!', 'Hello, 大冶!']

直接複数の呼び出しメソッドをサポートするために関数のシグネチャを更新することは、一般的で良いアプローチです。

ただし、場合によっては、別のアプローチを採用し、関数を呼び出すすべての方法を個別に定義する必要があるかもしれません。この方法は 関数のオーバーロード と呼ばれます。

2. 関数のオーバーロード

2 番目の方法は、関数のオーバーロード関数を使用することです。関数シグネチャが比較的複雑で、複数の型が含まれる場合は、このアプローチをお勧めします。

関数のオーバーロードを定義するには、オーバーロード シグネチャと実装シグネチャを定義する必要があります。

オーバーロード シグネチャは、関数本体なしで、関数の仮パラメーターと戻り値の型を定義します。関数には、関数を呼び出すさまざまな方法に対応する複数のオーバーロード シグネチャを含めることができます。

一方、実装シグネチャにはパラメータの型と戻り値の型もあり、実装関数の本体もあり、実装シグネチャは 1 つだけです。

// 重载签名
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() この関数には 2 つのオーバーロード シグネチャと 1 つの実装シグネチャがあります。

各オーバーロード シグネチャは、関数を呼び出す方法を記述します。 greet() 関数に関する限り、文字列パラメーターを使用する方法と文字列配列パラメーターを使用する方法の 2 つの方法で呼び出すことができます。

実装シグネチャ functiongreet(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: known): string と互換性がないとしてマークされています。

署名の

string 実装の戻り値の型は十分に一般的ではなく、オーバーロードされた署名の string[] 戻り値の型と互換性がありません。

3. メソッドのオーバーロード

前の例では、関数のオーバーロードは通常の関数に適用されています。ただし、メソッドをオーバーロードすることもできます。

メソッドのオーバーロード間隔では、オーバーロード シグネチャと実装シグネチャはクラスの一部です。

たとえば、オーバーロードされたメソッド

greet() を使用して Greeter クラスを実装します。

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 つのオーバーロード シグネチャと、正しい実装を含む実装シグネチャ

メソッドのオーバーロードにより、文字列を使用する方法とパラメータとして文字列の配列を使用する方法の 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 での関数のオーバーロードを使用すると、複数の方法で呼び出される関数を定義できます。

関数のオーバーロードを使用するには、オーバーロード シグネチャを定義する必要があります。オーバーロード シグネチャとは、パラメーターと戻り値の型を持つ関数のセットであり、本体は含まれません。これらのシグネチャは、関数を呼び出す方法を示します。

さらに、関数の正しい実装 (実装シグネチャ)、つまりパラメーターと戻り値の型、および関数本体 を記述する必要があります。実装シグネチャは呼び出し可能ではないことに注意してください。

通常の関数に加えて、クラス内のメソッドもオーバーロードできます。

英語の元のアドレス: https://dmitripavltin.com/typeript-function-overloading/

著者: dmitripavlutin

翻訳者: フロントエンド Xiaozhi

プログラミング関連の知識について詳しくは、プログラミング入門をご覧ください。 !

以上がTypeScriptで関数のオーバーロードを記述するにはどうすればよいですか?ライティングの紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。