Constructor Überlast in Maschinenschrift

stimmen
216

Hat jemand getan Konstruktor Überlastung in Typoskript. Auf Seite 64 der Sprachspezifikation (v 0.8), gibt es Aussagen beschreiben Konstruktorüberladungen, aber es gab keinen Beispielcode angegeben.

Ich versuche, eine wirklich grundlegende Klassendeklaration jetzt heraus; es sieht aus wie das,

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;
    }
}

Wenn mit tsc BoxSample.ts lief, wirft es ein Duplikat Konstruktordefinition aus - was offensichtlich ist. Jede Hilfe ist willkommen.

Veröffentlicht am 03/10/2012 um 06:48
quelle vom benutzer
In anderen Sprachen...                            


13 antworten

stimmen
190

Typoskript können Sie Überlastungen erklären, aber Sie können nur eine Implementierung haben und dass die Umsetzung muss eine Signatur, die mit allen Überlastungen kompatibel ist. In Ihrem Beispiel, kann dies leicht mit einem optionalen Parameter wie in getan werden,

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;
    }   
}

Überlastungen oder zwei mit einem allgemeineren Konstruktors wie in,

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;
    }   
}
Beantwortet am 03/10/2012 um 07:14
quelle vom benutzer

stimmen
63

Beachten Sie, dass Sie auch um den Mangel an Überlastung auf der Implementierungsebene durch Standardparameter in Typoskript arbeiten können, zum Beispiel:

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: Ab 5. Dezember '16 finden Benson Antwort für eine aufwändigere Lösung , die mehr Flexibilität ermöglicht.

Beantwortet am 09/10/2012 um 07:29
quelle vom benutzer

stimmen
48

In Bezug auf Konstruktorüberladungen eine Alternative , die zusätzliche Überlastungen zu implementieren wäre statische Factory - Methoden . Ich denke , die besser lesbar und weniger verwirrend als Ihren Anruf Argument testen. Hier ist ein einfaches Beispiel:

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'
})

Verfahren Überlastung in Typoskript ist nicht für echte , sagen wir mal, wie es zu viel Compiler generierte Code erfordern würde und das Kernteam versuchen , die Kosten auf allen zu vermeiden. Derzeit ist der Hauptgrund für die Methode auf der Sprache vorhanden seine Überlastung ist es, eine Möglichkeit zu bieten , um Erklärungen für Bibliotheken mit magischen Argumenten in ihrer API zu schreiben. Da Sie selbst alle schweres Heben zu tun brauchen unterschiedliche Sätze von Argumenten zu behandeln ich sehe nicht viel Vorteil in Überlastungen anstelle von getrennten Verfahren.

Beantwortet am 31/07/2016 um 21:08
quelle vom benutzer

stimmen
38

Hinweis: Diese wurde vereinfacht und 2017.04.13 aktualisiert, um Typoskript 2.1, siehe Geschichte für Typoskript 1.8 Antwort.

Es klingt wie Sie die Objektparameter werden optional möchten, und auch jedes der Objekte im Objekt optional sein. In dem Beispiel, wie es vorgesehen ist , Überlast - Syntax ist nicht erforderlich. Ich wollte hier einige schlechte Praktiken in der einige der Antworten hinweisen. Zugegeben, es ist nicht der kleinste mögliche Ausdruck im Wesentlichen zu schreiben box = { x: 0, y: 87, width: 4, height: 0 }, aber dies stellt alle Codes Hinting Nettigkeiten Sie möglicherweise aus der Klasse , wie beschrieben nur wünschen können. In diesem Beispiel können Sie eine Funktion mit einem nennen, einige, alle oder keine der Parameter und noch Standardwerte erhalten.

 /** @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;
     }
 }

Dies ist eine sehr sichere Art und Weise für die Parameter zu schreiben, die nicht alle Eigenschaften des Objekts definiert haben. Sie können nun sicher eine dieser schreiben:

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});  

Zusammengestellt, sehen Sie , dass die optionalen Parameter wirklich optional sind, dass die Gefahren eines weit verbreiteten vermeidet (aber fehleranfällig) Ausweich Syntax var = isOptional || default;durch Überprüfung vor void 0, die Abkürzung für ist undefined:

Die kompilierte Ausgabe

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;
}());

Nachtrag: Festlegen der Standardwerte: der falsche Weg

Der ||(oder) -Operator

Betrachten wir die Gefahr ||/ oder Betreiber als Standardfehlerwerte Einstellung wie in einigen anderen Antworten gezeigt. Dieser Code unten zeigt die falsche Art und Weise Standardwerte einzustellen. Sie können unerwartete Ergebnisse erhalten , wenn sie gegen die Bewertung Falsey Werte wie 0, ‚‘, null, nicht definiert, falsch, 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 (this, obj)

In meinen Tests es6 / Typoskript destructured Objekt mit fast 90% schneller als Object.assign sein . Nur einen destrukturierten Parameter verwenden , können Methoden und Eigenschaften , die Sie für das Objekt zugewiesen haben. Betrachten wir zum Beispiel diese Methode:

class BoxTest {
    public x?: number = 1;

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

Wenn ein anderer Benutzer nicht Typoskript mit und versucht , einen Parameter zu setzen , die nicht gehören, sagen wir, könnten sie versuchen , ein Putting - zEigenschaft

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')
Beantwortet am 05/12/2016 um 14:30
quelle vom benutzer

stimmen
32

Ich weiß, das ist eine alte Frage, aber neu in 1.4 sind Union-Typen; verwenden diese für alle Funktions Überlastungen (einschließlich Konstruktoren). Beispiel:

class foo {
    private _name: any;
    constructor(name: string | number) {
        this._name = name;
    }
}
var f1 = new foo("bar");
var f2 = new foo(1);
Beantwortet am 04/02/2015 um 18:28
quelle vom benutzer

stimmen
20

Update (8. Juni 2017): guyarad und snolflake gültige Punkte in ihren Kommentaren machen unten auf meine Antwort. Ich würde empfehlen , schauen Leser auf den Antworten von Benson , Joe und snolflake , die bessere Antworten als meine haben.

Original Antwort (27. Januar 2014)

Ein weiteres Beispiel dafür, wie Konstruktor Überlastung zu erreichen:

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;
    }
  }
}

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

Beantwortet am 27/01/2014 um 17:02
quelle vom benutzer

stimmen
3

In dem Fall, dass ein optionaler, typisierte Parameter gut genug ist, sollten Sie den folgenden Code, die ohne Wiederholung der Eigenschaften oder die Definition einer Schnittstelle das gleiche erreicht:

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

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

Denken Sie daran , wird diese zuweisen alle Eigenschaften übergeben track, eve , wenn sie auf nicht definiert sind Track.

Beantwortet am 06/11/2016 um 00:22
quelle vom benutzer

stimmen
1

Sie können dies umgehen, indem:

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);
    }
}

Teilweise werden Ihre Felder (x, y, Höhe, Breite) optionals, so dass mehrere Konstrukteure machen

zB: Sie tun können , new Box({x,y})ohne die Höhe und Breite.

Das = {}wird falsy Wert wie definiert, null etc, Griff und dann können Sie tunnew Box()

Beantwortet am 11/09/2018 um 09:36
quelle vom benutzer

stimmen
1

Eine andere Version wie auf @ ShinNoNoir Code, mit Standardwerten und Verbreitung Syntax:

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;
    }
}
Beantwortet am 30/11/2016 um 05:11
quelle vom benutzer

stimmen
0

Ich verwende die folgende alternative default / optional params und „Art-of-überlastet“ Konstrukteuren mit variabler Anzahl von params zu bekommen:

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

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

Ich weiß, es ist nicht das schönste Code immer, aber man gewöhnt sich daran. Keine Notwendigkeit für die zusätzliche Schnittstelle und erlaubt private Mitglieder, die nicht möglich ist, wenn die Schnittstelle.

Beantwortet am 20/09/2019 um 14:28
quelle vom benutzer

stimmen
0

Eigentlich könnte es für diese Antwort zu spät sein, aber Sie können dies jetzt tun:

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;
    }
}

so dass anstelle von statischen Methoden können Sie die oben tun. Ich hoffe es hilft dir!!!

Beantwortet am 26/05/2019 um 23:31
quelle vom benutzer

stimmen
0

Wir können Konstruktor Überlastung mit simulieren Wächter

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" })
Beantwortet am 27/03/2019 um 00:18
quelle vom benutzer

stimmen
0

Sie sollten diese im Sinn hatte ...

contructor ()

Konstruktor (a: beliebig, b: beliebig, c: any)

Es ist das gleiche von

new () oder neue ( "a", "b", "c")

So

Konstruktor (a: egal, b: egal, c: egal) ist die gleiche oben und ist flexibler ...

new () oder neue ( "a"), oder neue ( "a", "b") oder ein neues ( "a", "b", "c")

Beantwortet am 02/06/2018 um 14:15
quelle vom benutzer

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