Question

Existe-t-il un moyen de surcharger des méthodes en langage TypeScript ?

Je veux réaliser quelque chose comme ceci:

class TestClass {
    someMethod(stringParameter: string): void {
        alert("Variant #1: stringParameter = " + stringParameter);
    }

    someMethod(numberParameter: number, stringParameter: string): void {
        alert("Variant #2: numberParameter = " + numberParameter + ", stringParameter = " + stringParameter);
    }
}

var testClass = new TestClass();
testClass.someMethod("string for v#1");
testClass.someMethod(12345, "string for v#2");

Voici un exemple de ce que je ne veux pas faire (je déteste vraiment cette partie du hack de surcharge en JS) :

class TestClass {
    private someMethod_Overload_string(stringParameter: string): void {
        // A lot of code could be here... I don't want to mix it with switch or if statement in general function
        alert("Variant #1: stringParameter = " + stringParameter);
    }

    private someMethod_Overload_number_string(numberParameter: number, stringParameter: string): void {
        alert("Variant #2: numberParameter = " + numberParameter + ", stringParameter = " + stringParameter);
    }

    private someMethod_Overload_string_number(stringParameter: string, numberParameter: number): void {
        alert("Variant #3: stringParameter = " + stringParameter + ", numberParameter = " + numberParameter);
    }

    public someMethod(stringParameter: string): void;
    public someMethod(numberParameter: number, stringParameter: string): void;
    public someMethod(stringParameter: string, numberParameter: number): void;

    public someMethod(): void {
        switch (arguments.length) {
        case 1:
            if(typeof arguments[0] == "string") {
                this.someMethod_Overload_string(arguments[0]);
                return;
            }
            return; // Unreachable area for this case, unnecessary return statement
        case 2:
            if ((typeof arguments[0] == "number") &&
                (typeof arguments[1] == "string")) {
                this.someMethod_Overload_number_string(arguments[0], arguments[1]);
            }
            else if ((typeof arguments[0] == "string") &&
                     (typeof arguments[1] == "number")) {
                this.someMethod_Overload_string_number(arguments[0], arguments[1]);
            }
            return; // Unreachable area for this case, unnecessary return statement
        }
    }
}


var testClass = new TestClass();
testClass.someMethod("string for v#1");
testClass.someMethod(12345, "string for v#2");
testClass.someMethod("string for v#3", 54321);
Était-ce utile?

La solution

Selon la spécification, TypeScript prend la surcharge de la méthode de support, mais elle est assez gênante et inclut beaucoup de types de paramètres manuels de travail.Je pense que c'est surtout parce que le plus proche que vous puissiez accéder à la surcharge de la méthode dans la plaine JavaScript inclut que la vérification de la vérification aussi et Thypscript tente de ne pas modifier les organismes de méthodes réels afin d'éviter tout coût de performance d'exécution inutile.

Si je le comprends correctement, vous devez d'abord écrire une déclaration de méthode pour chacune des surcharges, puis un la mise en œuvre de la méthode qui vérifie ses arguments pour décider quelle surcharge a été appelée.La signature de la mise en œuvre doit être compatible avec toutes les surcharges.

class TestClass {
    someMethod(stringParameter: string): void;
    someMethod(numberParameter: number, stringParameter: string): void;

    someMethod(stringOrNumberParameter: any, stringParameter?: string): void {
        if (stringOrNumberParameter && typeof stringOrNumberParameter == "number")
            alert("Variant #2: numberParameter = " + stringOrNumberParameter + ", stringParameter = " + stringParameter);
        else
            alert("Variant #1: stringParameter = " + stringOrNumberParameter);
    }
}

Autres conseils

Mise à jour pour plus de clarté.La surcharge de méthodes dans TypeScript est une fonctionnalité utile dans la mesure où elle vous permet de créer des définitions de types pour les bibliothèques existantes avec une API qui doit être représentée.

Cependant, lorsque vous écrivez votre propre code, vous pourrez peut-être éviter la surcharge cognitive liée aux surcharges en utilisant des paramètres facultatifs ou par défaut.C'est l'alternative la plus lisible aux surcharges de méthodes et maintient également votre API honnête car vous éviterez de créer des surcharges avec un ordre peu intuitif.

La loi générale des surcharges TypeScript est la suivante :

Si vous pouvez supprimer les signatures de surcharge et que tous vos tests réussissent, vous n'avez pas besoin de surcharges TypeScript

Vous pouvez généralement obtenir la même chose avec des paramètres facultatifs ou par défaut - ou avec des types d'union, ou avec un peu d'orientation objet.

La vraie question

La vraie question demande une surcharge de :

someMethod(stringParameter: string): void {

someMethod(numberParameter: number, stringParameter: string): void {

Désormais, même dans les langages prenant en charge les surcharges avec des implémentations distinctes (remarque :Les surcharges TypeScript partagent une seule implémentation) - les programmeurs sont invités à assurer la cohérence dans l'ordre.Cela ferait les signatures :

someMethod(stringParameter: string): void {

someMethod(stringParameter: string, numberParameter: number): void {

Le stringParameter est toujours obligatoire, donc cela commence en premier.Vous pouvez écrire ceci comme une surcharge TypeScript fonctionnelle :

someMethod(stringParameter: string): void;
someMethod(stringParameter: string, numberParameter: number): void;
someMethod(stringParameter: string, numberParameter?: number): void {
    if (numberParameter != null) {
        // The number parameter is present...
    }
}

Mais suivant la loi des surcharges TypeScript, nous pouvons supprimer les signatures de surcharge et tous nos tests réussiront toujours.

someMethod(stringParameter: string, numberParameter?: number): void {
    if (numberParameter != null) {
        // The number parameter is present...
    }
}

La vraie question, dans l’ordre réel

Si vous étiez déterminé à conserver la commande initiale, les surcharges seraient :

someMethod(stringParameter: string): void;
someMethod(numberParameter: number, stringParameter: string): void;
someMethod(a: string | number, b?: string | number): void {
  let stringParameter: string;
  let numberParameter: number;

  if (typeof a === 'string') {
    stringParameter = a;
  } else {
    numberParameter = a;

    if (typeof b === 'string') {
      stringParameter = b;
    }
  }
}

Maintenant, cela fait beaucoup de branchements pour déterminer où placer les paramètres, mais vous vouliez vraiment conserver cet ordre si vous lisez jusqu'ici...mais attendez, que se passe-t-il si nous appliquons la loi des surcharges TypeScript ?

someMethod(a: string | number, b?: string | number): void {
  let stringParameter: string;
  let numberParameter: number;

  if (typeof a === 'string') {
    stringParameter = a;
  } else {
    numberParameter = a;

    if (typeof b === 'string') {
      stringParameter = b;
    }
  }
}

Assez de ramifications déjà

Bien sûr, étant donné la quantité de vérification de type que nous devons effectuer...peut-être que la meilleure réponse est simplement d'avoir deux méthodes :

someMethod(stringParameter: string): void {
  this.someOtherMethod(0, stringParameter);
}

someOtherMethod(numberParameter: number, stringParameter: string): void {
  //...
}

Je souhaite.Je veux aussi cette fonctionnalité, mais le type de documents doit être interopérable avec JavaScript non typé qui n'a pas de méthodes surchargées.I.e. Si votre méthode surchargée est appelée à partir de JavaScript, elle ne peut être expédiée qu'à une méthode implémentation.

Il y a quelques discussions pertinentes sur CodePlex.par exemple.

https://typescript.codeplex.com/workitem/617

Je pense toujours que le type doctorant devrait générer tout l'if'ing et le commutation afin de ne pas avoir besoin de le faire.

Pourquoi ne pas utiliser Interface de propriété en option comme L'argument de la fonction ..

Pour le cas dans cette question, l'utilisation d'une interface intégrée définie avec certaines propriétés facultatives ne pouvait que créer directement du code comme quelque chose ci-dessous:

class TestClass {

    someMethod(arg: { stringParameter: string, numberParameter?: number }): void {
        let numberParameterMsg = "Variant #1:";
        if (arg.numberParameter) {
            numberParameterMsg = `Variant #2: numberParameter = ${arg.numberParameter},`;
        }
        alert(`${numberParameterMsg} stringParameter = ${arg.stringParameter}`);
    }
}

var testClass = new TestClass();
testClass.someMethod({ stringParameter: "string for v#1" });
testClass.someMethod({ numberParameter: 12345, stringParameter: "string for v#2" });

Étant donné que la surcharge fournie dans Typescript est, comme indiqué dans les commentaires des autres, une liste des signatures différentes de la fonction sans prendre en charge les codes de mise en œuvre correspondants tels que les autres langues statiques. Donc, la mise en œuvre doit encore être effectuée dans un seul organe de fonction, ce qui rend l'utilisation de la fonction de surcharge de fonction dans les documents non confortables que ces langues prenant en charge la fonctionnalité de surcharge réelle.

Cependant, il reste encore beaucoup de choses nouvelles et pratiques fournies dans TypeScript qui n'est pas disponible en langage de programmation hérité, où la prise en charge des biens optionnels dans une interface anonyme est une telle approche pour répondre à la zone confortable de la surcharge de la fonction héritée, je pense .

JavaScript n'a aucun concept de surcharge.Typescript n'est pas C # ou Java.

Mais vous pouvez mettre en œuvre la surcharge dans TypeScript.

lire ce post http://www.gyanparkash.in/function-overooPloadering-in-typeScript/

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top