Heim  >  Artikel  >  Web-Frontend  >  Wie schreibe ich eine Funktionsüberladung in TypeScript? Einführung in das Schreiben

Wie schreibe ich eine Funktionsüberladung in TypeScript? Einführung in das Schreiben

青灯夜游
青灯夜游nach vorne
2021-12-14 10:37:011933Durchsuche

Wie schreibe ich eine Funktionsüberladung in TypeScript? Der folgende Artikel zeigt Ihnen, wie Sie Funktionsüberladungen in TypeScript schreiben. Ich hoffe, er wird Ihnen hilfreich sein!

Wie schreibe ich eine Funktionsüberladung in TypeScript? Einführung in das Schreiben

Die meisten Funktionen akzeptieren einen festen Parametersatz.

Aber einige Funktionen können eine variable Anzahl von Argumenten und unterschiedliche Argumenttypen akzeptieren und sogar unterschiedliche Typen zurückgeben, je nachdem, wie Sie die Funktion aufrufen. Um solche Funktionen mit Anmerkungen zu versehen, bietet TypeScript eine Funktionsüberladung.

1. Funktionssignatur

Betrachten wir zunächst eine Funktion, die eine Begrüßungsnachricht an eine bestimmte Person zurückgibt.

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

Die obige Funktion akzeptiert 1 Zeichentypparameter: den Namen der Person. Der Aufruf dieser Funktion ist sehr einfach:

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

Was ist, wenn Sie die Funktion greet() flexibler gestalten möchten? Lassen Sie es beispielsweise auch eine Liste der zu begrüßenden Personen erstellen. 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()

Eine solche Funktion akzeptiert einen String oder ein Array von Strings als Argument und gibt einen String oder ein Array von Strings zurück.

Wie kommentiere ich eine solche Funktion? Es gibt zwei Möglichkeiten.

Die erste Methode ist sehr einfach. Sie besteht darin, die Funktionssignatur direkt zu ändern, indem die Parameter und der Rückgabetyp aktualisiert werden. Unten sehen Sie, wie greet() nach dem Refactoring aussieht:

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

Jetzt können wir greet() auf zwei Arten aufrufen:

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

Aktualisieren Sie die Funktionssignatur direkt zur Unterstützung multiple Diese aufrufende Methode ist eine gängige und gute Methode.

In einigen Fällen müssen wir jedoch möglicherweise einen anderen Ansatz wählen und alle Arten, wie Ihre Funktion aufgerufen werden kann, separat definieren. Dieser Ansatz wird „Funktionsüberladung“ genannt.

2. Funktionsüberladung

Die zweite Methode ist die Verwendung der Funktionsüberladungsfunktion. Ich empfehle diesen Ansatz, wenn die Funktionssignatur relativ komplex ist und mehrere Typen umfasst.

Um eine Funktionsüberladung zu definieren, müssen eine Überlastungssignatur und eine Implementierungssignatur definiert werden.

Die überladene Signatur definiert die formalen Parameter und den Rückgabetyp der Funktion, ohne Funktionskörper. Eine Funktion kann mehrere Überladungssignaturen haben: entsprechend unterschiedlichen Aufrufmethoden der Funktion. 🎜🎜Andererseits verfügt die Implementierungssignatur auch über Parametertypen und Rückgabetypen sowie über den Hauptteil der Implementierungsfunktion, und es kann nur eine Implementierungssignatur geben. Die Funktion 🎜
// 推荐做法
function myFunc(param1?: string, param2: string): string {
  // implementation...
}
🎜greet() hat zwei Überladungssignaturen und eine Implementierungssignatur. 🎜🎜Jede Überladungssignatur beschreibt eine Art und Weise, wie die Funktion aufgerufen werden kann. Was die Funktion greet() betrifft, können wir sie auf zwei Arten aufrufen: mit einem String-Parameter oder mit einem String-Array-Parameter. 🎜🎜Die Implementierungssignatur functiongreet(person:known):unknown { ... enthält die entsprechende Logik für die Funktionsweise der Funktion. 🎜🎜Jetzt kann greet() wie oben mit Argumenten vom Typ String oder Array von Strings aufgerufen werden. 🎜rrreee🎜🎜2.1 Überladene Signatur ist aufrufbar🎜🎜🎜Obwohl die Implementierungssignatur das Funktionsverhalten implementiert, kann sie nicht direkt aufgerufen werden. Es sind nur überladene Signaturen aufrufbar. 🎜rrreee🎜Im obigen Beispiel können Sie greet() nicht mit einem Parameter vom Typ <code>unknown (greet(someValue))unknown-Parameter akzeptiert /code> ) Funktion. 🎜🎜🎜2.2 Implementierungssignatur muss universell sein🎜🎜rrreee🎜Überladungssignaturfunktion greet(person: string[]): string[] code> ist als inkompatibel mit <code>greet(person: unbekannt): string markiert. 🎜🎜Die Implementierung signierter string-Rückgabetypen ist nicht allgemein genug und nicht mit der Überladung signierter string[]-Rückgabetypen kompatibel. 🎜🎜🎜3. Methodenüberladung🎜🎜🎜Obwohl im vorherigen Beispiel die Funktionsüberladung auf eine normale Funktion angewendet wurde. Wir können aber auch eine Methode überladen🎜🎜Im Methodenüberladungsintervall sind die Überladungssignatur und die Implementierungssignatur Teil der Klasse. 🎜🎜Zum Beispiel implementieren wir eine Greeter-Klasse mit einer überladenen Methode greet(). 🎜rrreee🎜🎜Greeter🎜 Die Klasse enthält überladene greet()-Methoden: 2 überladene Signaturen, die beschreiben, wie die Methode aufgerufen wird, und eine Implementierungssignatur, die die korrekte Implementierung enthält. 🎜🎜Aufgrund der Methodenüberladung können wir verwenden Es gibt zwei Möglichkeiten, hi.greet() aufzurufen: mit einem String oder mit einem Array von Strings als Argument. 🎜rrreee🎜🎜4. Wann man Funktionsüberladung verwenden sollte🎜🎜🎜Funktionsüberladung kann bei richtiger Anwendung die Benutzerfreundlichkeit einer Funktion, die auf verschiedene Arten aufgerufen werden kann, erheblich erhöhen. Dies ist besonders nützlich bei der automatischen Vervollständigung: Wir listen alle möglichen Überladungen in der automatischen Vervollständigung auf. 🎜🎜In einigen Fällen wird jedoch empfohlen, keine Funktionsüberladung zu verwenden und stattdessen Funktionssignaturen zu verwenden. 🎜🎜 Verwenden Sie beispielsweise keine Funktionsüberladung für optionale Parameter: 🎜rrreee🎜 Es ​​reicht aus, optionale Parameter in der Funktionssignatur zu verwenden: 🎜rrreee🎜🎜 5. Zusammenfassung 🎜🎜🎜 Funktionsüberladung in TypeScript Definieren wir so viele aufgerufene Funktionen Hier entlang. 🎜🎜Die Verwendung der Funktionsüberladung erfordert die Definition einer Überladungssignatur: eine Reihe von Funktionen mit Parametern und Rückgabetypen, aber ohne Hauptteil. Diese Signaturen geben an, wie die Funktion aufgerufen werden soll. 🎜

Darüber hinaus müssen Sie die korrekte Implementierung (Implementierungssignatur) der Funktion ausschreiben: Parameter und Rückgabetypen sowie den Funktionskörper . Beachten Sie, dass Implementierungssignaturen nicht aufrufbar sind.

Neben regulären Funktionen können auch Methoden in Klassen überladen werden.

Englische Originaladresse: https://dmitripavltin.com/typeript-function-overloading/

Autor: dmitripavlutin

Übersetzer: Front-end Xiaozhi

Weitere Programmierkenntnisse finden Sie unter: Einführung in Programmieren ! !

Das obige ist der detaillierte Inhalt vonWie schreibe ich eine Funktionsüberladung in TypeScript? Einführung in das Schreiben. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen