surcharge Constructor dactylographiée

voix
216

A la surcharge constructeur fait de qui que ce soit dactylographiée. A la page 64 de la spécification du langage (v 0.8), il y a des déclarations qui décrivent constructeur surcharges, mais il n'y avait pas de code d'échantillon donné.

J'essaie une déclaration de classe vraiment de base en ce moment; il ressemble à ceci,

interface IBox {    
    x : number;
    y : number;
    height : number;
    width : number;
}

class Box {
    public x: number;
    public y: number;
    public height: number;
    public width: number;

    constructor(obj: IBox) {    
        this.x = obj.x;
        this.y = obj.y;
        this.height = obj.height;
        this.width = obj.width;
    }   

    constructor() {
        this.x = 0;
        this.y = 0;
        this.width = 0;
        this.height = 0;
    }
}

Quand couru avec BoxSample.ts TSC, il jette une définition de constructeur en double - ce qui est évident. Toute aide est appréciée.

Créé 03/10/2012 à 06:48
source utilisateur
Dans d'autres langues...                            


13 réponses

voix
190

Tapuscrit vous permet de déclarer, mais vous ne surcharge peut avoir une mise en œuvre et que la mise en œuvre doit avoir une signature qui est compatible avec tous les surcharges. Dans votre exemple, cela peut se faire facilement avec un paramètre optionnel comme,

interface IBox {    
    x : number;
    y : number;
    height : number;
    width : number;
}

class Box {
    public x: number;
    public y: number;
    public height: number;
    public width: number;

    constructor(obj?: IBox) {    
        this.x = obj && obj.x || 0
        this.y = obj && obj.y || 0
        this.height = obj && obj.height || 0
        this.width = obj && obj.width || 0;
    }   
}

ou deux surcharges avec un constructeur plus générale comme dans,

interface IBox {    
    x : number;
    y : number;
    height : number;
    width : number;
}

class Box {
    public x: number;
    public y: number;
    public height: number;
    public width: number;

    constructor();
    constructor(obj: IBox); 
    constructor(obj?: any) {    
        this.x = obj && obj.x || 0
        this.y = obj && obj.y || 0
        this.height = obj && obj.height || 0
        this.width = obj && obj.width || 0;
    }   
}
Créé 03/10/2012 à 07:14
source utilisateur

voix
63

Notez que vous pouvez également contourner l'absence de surcharge au niveau de la mise en œuvre par les paramètres par défaut dactylographiée, par exemple:

interface IBox {    
    x : number;
    y : number;
    height : number;
    width : number;
}

class Box {
    public x: number;
    public y: number;
    public height: number;
    public width: number;

    constructor(obj : IBox = {x:0,y:0, height:0, width:0}) {    
        this.x = obj.x;
        this.y = obj.y;
        this.height = obj.height;
        this.width = obj.width;
    }   
}

Edit: Au 5 décembre '16, voir la réponse de Benson une solution plus élaborée qui permet une plus grande flexibilité.

Créé 09/10/2012 à 07:29
source utilisateur

voix
48

En ce qui concerne surchargent constructeur une alternative serait de mettre en œuvre les autres que les surcharges méthodes statiques d'usine . Je pense que plus lisible et moins déroutant que de tester vos arguments d'appel. Voici un exemple simple:

class Person {
    static fromData(data: PersonData) {
        let { first, last, birthday, gender = 'M' } = data 
        return new this(
            `${last}, ${first}`,
            calculateAge(birthday),
            gender
        )
    }

    constructor(
        public fullName: string,
        public age: number,
        public gender: 'M' | 'F'
    ) {}
}

interface PersonData {
    first: string
    last: string
    birthday: string
    gender?: 'M' | 'F'
}


let personA = new Person('Doe, John', 31, 'M')
let personB = Person.fromData({
    first: 'John',
    last: 'Doe',
    birthday: '10-09-1986'
})

Méthode surchargeant dactylographiée est pas pour de vrai , disons, car cela nécessiterait trop de code généré par le compilateur et l'équipe de base essayer d'éviter à tout prix. Actuellement , la principale raison de Overload être présent sur la langue est de fournir un moyen d'écrire des déclarations pour les bibliothèques avec des arguments magiques dans leur API. Étant donné que vous aurez besoin de faire tout le levage lourd par vous - même pour gérer différents ensembles d'arguments que je ne vois pas beaucoup d' avantage à utiliser au lieu des méthodes surcharges séparées.

Créé 31/07/2016 à 21:08
source utilisateur

voix
38

Note: ceci a été simplifié et mis à jour pour refléter 13/04/2017 tapuscrit 2.1, voir l'histoire pour la réponse tapuscrit 1.8.

On dirait que vous voulez que le paramètre objet à option, ainsi que chacune des propriétés de l'objet à être en option. Dans l'exemple, comme prévu, la syntaxe de surcharge n'est pas nécessaire. Je voulais souligner certaines mauvaises pratiques dans l'une des réponses ici. Certes, ce n'est pas la plus petite expression possible d'écrire essentiellement box = { x: 0, y: 87, width: 4, height: 0 }, mais cela fournit tous les conseils de code politesses que vous pourriez vouloir de la classe comme décrit. Cet exemple vous permet d'appeler une fonction avec un, certains, tous, ou aucun des paramètres et obtenez toujours des valeurs par défaut.

 /** @class */
 class Box {
     public x?: number;
     public y?: number;
     public height?: number;
     public width?: number;     

     // The class can work double-duty as the interface here since they are identical
     // Alternately, reference your own interface, e.g.:  `...BoxI = {} as BoxI` 
     constructor(obj: Box = {} as Box) {

         // Define the properties of the incoming `obj` object here. 
         // Setting a default value with the `= 0` syntax is optional for each parameter
         let {
             x = 0,
             y = 0,
             height = 0,
             width = 0
         } = obj;

         /** Use jsdoc comments here for inline ide auto-documentation */
         this.x = x;
         this.y = y;
         this.height = height;
         this.width = width;
     }
 }

Ceci est un moyen très sûr d'écrire pour les paramètres qui peuvent ne pas avoir toutes les propriétés de l'objet défini. Vous pouvez maintenant en toute sécurité écrire un de ces:

const box1 = new Box();
const box2 = new Box({});
const box3 = new Box({x:0});
const box4 = new Box({x:0, height:10});
const box5 = new Box({x:0, y:87,width:4,height:0});

 // Correctly reports error in TypeScript, and in js, box6.z is undefined
const box6 = new Box({z:0});  

Compilé, vous voyez que les paramètres facultatifs sont vraiment en option, qui permet d' éviter les pièges d'un largement utilisé (mais sujette aux erreurs) syntaxe de repli var = isOptional || default;en vérifiant contre void 0, ce qui est un raccourci pour undefined:

La sortie compilée

var Box = (function () {
    function Box(obj) {
        if (obj === void 0) { obj = {}; }
        var _a = obj.x, 
        x = _a === void 0 ? 1 : _a,
        _b = obj.y,
        y = _b === void 0 ? 1 : _b,
        _c = obj.height,
        height = _c === void 0 ? 1 : _c,
        _d = obj.width,
        width = _d === void 0 ? 1 : _d;
        this.x = x;
        this.y = y;
        this.height = height;
        this.width = width;
    }
    return Box;
}());

Addendum: Définition des valeurs par défaut: la mauvaise façon

L' ||opérateur (ou)

Considérez le danger de ||/ ou les opérateurs lors de la configuration des valeurs de repli par défaut comme indiqué dans d'autres réponses. Ce code ci - dessous illustre la mauvaise façon de définir les valeurs par défaut. Vous pouvez obtenir des résultats inattendus lors de l' évaluation contre Falsey valeurs telles que 0, « », null, non défini, faux, NaN:

var myDesiredValue = 0;
var result = myDesiredValue || 2;

// This test will correctly report a problem with this setup.
console.assert(myDesiredValue === result && result === 0, 'Result should equal myDesiredValue. ' + myDesiredValue + ' does not equal ' + result);

Object.assign (ce, obj)

Dans mes tests, en utilisant ES6 / tapuscrit objet déstructuré peut être près de 90% plus rapide que Object.assign . L' utilisation d' un paramètre déstructuré ne permet que des méthodes et des propriétés que vous avez attribué à l'objet. Par exemple, considérons cette méthode:

class BoxTest {
    public x?: number = 1;

    constructor(obj: BoxTest = {} as BoxTest) {
        Object.assign(this, obj);
    }
}

Si un autre utilisateur n'a pas utilisé tapuscrit et a tenté de placer un paramètre qui ne lui appartenait pas, par exemple, ils pourraient essayer de mettre une zpropriété

var box = new BoxTest({x: 0, y: 87, width: 4, height: 0, z: 7});

// This test will correctly report an error with this setup. `z` was defined even though `z` is not an allowed property of obj.
console.assert(typeof box.z === 'undefined')
Créé 05/12/2016 à 14:30
source utilisateur

voix
32

Je sais que c'est une vieille question, mais nouveau dans 1.4 est les types syndicaux; les utiliser pour toutes les fonctions de surcharge (y compris les constructeurs). Exemple:

class foo {
    private _name: any;
    constructor(name: string | number) {
        this._name = name;
    }
}
var f1 = new foo("bar");
var f2 = new foo(1);
Créé 04/02/2015 à 18:28
source utilisateur

voix
20

Mise à jour (8 Juin 2017): guyarad et snolflake faire des points valides dans leurs commentaires ci - dessous ma réponse. Je recommande aux lecteurs de consulter les réponses par Benson , Joe et snolflake qui ont de meilleures réponses que la mienne.

Réponse d'origine (27 Janvier 2014)

Un autre exemple de la façon d'atteindre constructeur surcharge:

class DateHour {

  private date: Date;
  private relativeHour: number;

  constructor(year: number, month: number, day: number, relativeHour: number);
  constructor(date: Date, relativeHour: number);
  constructor(dateOrYear: any, monthOrRelativeHour: number, day?: number, relativeHour?: number) {
    if (typeof dateOrYear === "number") {
      this.date = new Date(dateOrYear, monthOrRelativeHour, day);
      this.relativeHour = relativeHour;
    } else {
      var date = <Date> dateOrYear;
      this.date = new Date(date.getFullYear(), date.getMonth(), date.getDate());
      this.relativeHour = monthOrRelativeHour;
    }
  }
}

Source: http://mimosite.com/blog/post/2013/04/08/Overloading-in-TypeScript

Créé 27/01/2014 à 17:02
source utilisateur

voix
3

Dans le cas où un paramètre optionnel, tapé est assez bon, considérez le code suivant qui accomplit le même sans répéter les propriétés ou la définition d'une interface:

export class Track {
   public title: string;
   public artist: string;
   public lyrics: string;

   constructor(track?: Track) {
     Object.assign(this, track);
   }
}

Gardez à l' esprit ce assignera toutes les propriétés transmises à track, veille si elles ne sont pas définies Track.

Créé 06/11/2016 à 00:22
source utilisateur

voix
1

Vous pouvez gérer cela par:

import { assign } from 'lodash'; // if you don't have lodash use Object.assign
class Box {
    x: number;
    y: number;
    height: number;
    width: number;
    constructor(obj: Partial<Box> = {}) {    
         assign(this, obj);
    }
}

Partielle fera vos champs (x, y, hauteur, largeur) optionals, ce qui permet de multiples constructeurs

par exemple: vous pouvez le faire new Box({x,y})sans la hauteur et la largeur.

La = {}manipulera valeur falsy telle que définie etc, null, et vous pouvez le fairenew Box()

Créé 11/09/2018 à 09:36
source utilisateur

voix
1

Une autre version comme au code de @ ShinNoNoir, en utilisant des valeurs par défaut et la syntaxe de diffusion:

class Box {
    public x: number;
    public y: number;
    public height: number;
    public width: number;

    constructor({x, y, height, width}: IBox = { x: 0, y: 0, height: 0, width: 0 }) {
        this.x = x;
        this.y = y;
        this.height = height;
        this.width = width;
    }
}
Créé 30/11/2016 à 05:11
source utilisateur

voix
0

J'utilise la alternative suivante pour obtenir défaut / option params et « de type de surcharge » constructeurs avec nombre variable de params:

private x?: number;
private y?: number;

constructor({x = 10, y}: {x?: number, y?: number}) {
 this.x = x;
 this.y = y;
}

Je sais que ce n'est pas le code plus joli jamais, mais on finit par s'y habituer. Pas besoin de l'interface supplémentaire et permet aux membres privés, ce qui est impossible lors de l'utilisation de l'interface.

Créé 20/09/2019 à 14:28
source utilisateur

voix
0

En fait, il pourrait être trop tard pour cette réponse, mais vous pouvez maintenant faire ceci:

class Box {
    public x: number;
    public y: number;
    public height: number;
    public width: number;

    constructor();
    constructor(obj: IBox);
    constructor(obj?: IBox) {    
        this.x = !obj ? 0 : obj.x;
        this.y = !obj ? 0 : obj.y;
        this.height = !obj ? 0 : obj.height;
        this.width = !obj ? 0 : obj.width;
    }
}

donc au lieu de méthodes statiques que vous pouvez faire ce qui précède. J'espère que cela vous aidera !!!

Créé 26/05/2019 à 23:31
source utilisateur

voix
0

Nous pouvons simuler une surcharge constructeur à l' aide des gardes

interface IUser {
  name: string;
  lastName: string;
}

interface IUserRaw {
  UserName: string;
  UserLastName: string;
}

function isUserRaw(user): user is IUserRaw {
  return !!(user.UserName && user.UserLastName);
}

class User {
  name: string;
  lastName: string;

  constructor(data: IUser | IUserRaw) {
    if (isUserRaw(data)) {
      this.name = data.UserName;
      this.lastName = data.UserLastName;
    } else {
      this.name = data.name;
      this.lastName = data.lastName;
    }
  }
}

const user  = new User({ name: "Jhon", lastName: "Doe" })
const user2 = new User({ UserName: "Jhon", UserLastName: "Doe" })
Créé 27/03/2019 à 00:18
source utilisateur

voix
0

Vous devriez eu à l'esprit que ...

contructor ()

constructeur (a: y en a, b: tout, c: y en a)

Il en est de même de

new () ou nouvelle ( "a", "b", "c")

Ainsi

constructeur (a: y en a, b: tout, c: y en a) ci-dessus est le même et est plus souple ...

new () ou nouvelle ( "a") ou nouvelle ( "a", "b") ou nouvelle ( "a", "b", "c")

Créé 02/06/2018 à 14:15
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more