Maison >interface Web >js tutoriel >Comment écrire une surcharge de fonctions en TypeScript ? Introduction à l'écriture

Comment écrire une surcharge de fonctions en TypeScript ? Introduction à l'écriture

青灯夜游
青灯夜游avant
2021-12-14 10:37:012047parcourir

Comment écrire une surcharge de fonctions en TypeScript ? L'article suivant vous présentera comment écrire une surcharge de fonctions dans TypeScript. J'espère qu'il vous sera utile !

Comment écrire une surcharge de fonctions en TypeScript ? Introduction à l'écriture

La plupart des fonctions acceptent un ensemble fixe de paramètres.

Mais certaines fonctions peuvent accepter un nombre variable d'arguments, différents types d'arguments, et même renvoyer différents types selon la façon dont vous appelez la fonction. Pour annoter de telles fonctions, TypeScript fournit une surcharge de fonctions.

1. Signature de fonction

Considérons d'abord une fonction qui renvoie un message de bienvenue à une personne spécifique.

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

La fonction ci-dessus accepte 1 paramètre de type de caractère : le nom de la personne. Appeler cette fonction est très simple :

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

Et si vous souhaitez rendre la fonction greet() plus flexible ? Par exemple, laissez-le accepter en plus une liste de personnes à saluer. 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()

Une telle fonction acceptera une chaîne ou un tableau de chaînes comme argument et renverra une chaîne ou un tableau de chaînes.

Comment annoter une telle fonction ? Il y a 2 façons.

La première méthode est très simple, elle consiste à modifier directement la signature de la fonction en mettant à jour les paramètres et le type de retour. Voici à quoi ressemble greet() après la refactorisation :

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

Maintenant, nous pouvons appeler greet() de deux manières :

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

Mettre à jour directement la signature de la fonction pour prendre en charge multiple Cette méthode d'appel est une méthode courante et bonne.

Cependant, dans certains cas, nous devrons peut-être adopter une autre approche et définir séparément toutes les manières dont votre fonction peut être appelée. Cette approche est appelée

surcharge de fonctions.

2. Surcharge de fonctions

La deuxième méthode consiste à utiliser la fonction de surcharge de fonctions. Je recommande cette approche lorsque la signature de fonction est relativement complexe et implique plusieurs types.

Définir une surcharge de fonction nécessite de définir une signature de surcharge et une signature d'implémentation. 🎜🎜La signature surchargée définit les paramètres formels et le type de retour de la fonction, sans corps de fonction. Une fonction peut avoir plusieurs signatures de surcharge : correspondant à différentes manières d'appeler la fonction. 🎜🎜D'un autre côté, la signature d'implémentation a également des types de paramètres et des types de retour, ainsi que le corps de la fonction d'implémentation, et il ne peut y avoir qu'une seule signature d'implémentation. La fonction 🎜
// 推荐做法
function myFunc(param1?: string, param2: string): string {
  // implementation...
}
🎜greet() a deux signatures de surcharge et une signature d'implémentation. 🎜🎜Chaque signature de surcharge décrit la manière dont la fonction peut être appelée. En ce qui concerne la fonction greet(), on peut l'appeler de deux manières : avec un paramètre chaîne, ou avec un paramètre tableau de chaînes. 🎜🎜La signature d'implémentation function greet(person: unknown): unknown { ... } contient la logique appropriée au fonctionnement de la fonction. 🎜🎜Maintenant, comme ci-dessus, greet() peut être appelé avec des arguments de type chaîne ou tableau de chaînes. 🎜rrreee🎜🎜2.1 La signature surchargée est appelable🎜🎜🎜Bien que la signature d'implémentation implémente le comportement de la fonction, elle ne peut pas être appelée directement. Seules les signatures surchargées sont appelables. 🎜rrreee🎜Dans l'exemple ci-dessus, même si la signature d'implémentation accepte les paramètres inconnu, la fonction greet( ). 🎜🎜🎜2.2 La signature d'implémentation doit être universelle🎜🎜rrreee🎜Surcharge de la fonction de signature greet(person: string[]): string[] code> est marqué comme incompatible avec <code>greet(person: unknown): string. 🎜🎜L'implémentation du type de retour signé string n'est pas assez général et n'est pas compatible avec le type de retour signé string[] surchargé. 🎜🎜🎜3. Surcharge de méthode🎜🎜🎜Bien que dans l'exemple précédent, la surcharge de fonction ait été appliquée à une fonction normale. Mais on peut aussi surcharger une méthode🎜🎜Dans l'intervalle de surcharge de méthode, la signature de surcharge et la signature d'implémentation font partie de la classe. 🎜🎜Par exemple, nous implémentons une classe Greeter avec une méthode surchargée greet(). 🎜rrreee🎜🎜Greeter🎜 La classe contient des méthodes surchargées greet() : 2 signatures de surcharge décrivant comment appeler la méthode, et une signature d'implémentation contenant l'implémentation correcte🎜🎜En raison de la surcharge de la méthode, nous pouvons utiliser Il existe deux manières d'appeler hi.greet() : avec une chaîne ou avec un tableau de chaînes comme argument. 🎜rrreee🎜🎜4. Quand utiliser la surcharge de fonctions🎜🎜🎜La surcharge de fonctions, si elle est utilisée correctement, peut considérablement augmenter la convivialité d'une fonction qui peut être appelée de plusieurs manières. Ceci est particulièrement utile lors de l'auto-complétion : nous listons toutes les surcharges possibles en auto-complétion. 🎜🎜Cependant, dans certains cas, il est recommandé de ne pas utiliser la surcharge de fonctions et d'utiliser plutôt des signatures de fonction. 🎜🎜 Par exemple, n'utilisez pas la surcharge de fonctions pour les paramètres facultatifs : 🎜rrreee🎜 Il suffit d'utiliser des paramètres facultatifs dans la signature de la fonction : 🎜rrreee🎜🎜 5. Résumé 🎜🎜🎜 Surcharge de fonctions dans TypeScript Définissons le plus grand nombre de fonctions appelées dans Par ici. 🎜🎜L'utilisation de la surcharge de fonctions nécessite de définir une signature de surcharge : un ensemble de fonctions avec des paramètres et des types de retour, mais pas de corps. Ces signatures indiquent comment la fonction doit être appelée. 🎜

De plus, vous devez rédiger l'implémentation correcte (signature d'implémentation) de la fonction : paramètres et types de retour, ainsi que le corps de la fonction . Notez que les signatures d'implémentation ne sont pas appelables.

En plus des fonctions habituelles, les méthodes des classes peuvent également être surchargées.

Adresse originale en anglais : https://dmitripavltin.com/typeript-function-overloading/

Auteur : dmitripavlutin

Traducteur : Front-end Xiaozhi

Pour plus de connaissances liées à la programmation, veuillez visiter : Introduction à Programmation ! !

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer