Frage Wie man ein neues Objekt vom Typparameter in der generischen Klasse in typescript erzeugt?


Ich versuche ein neues Objekt eines Typparameters in meiner generischen Klasse zu erstellen. In meiner Klasse "View" habe ich 2 Listen von Objekten vom generischen Typ als Typparameter übergeben, aber wenn ich versuche zu machen new TGridView() Typoskript sagt Could not find symbol 'TGridView'...

Dies ist der Code:

module AppFW {
    // Represents a view
    export class View<TFormView extends FormView, TGridView extends GridView> {
        // The list of forms 
        public Forms: { [idForm: string]: TFormView; } = {};

        // The list of grids
        public Grids: { [idForm: string]: TGridView; } = {};

        public AddForm(formElement: HTMLFormElement, dataModel: any, submitFunction?: (e: SubmitFormViewEvent) => boolean): FormView {
            var newForm: TFormView = new TFormView(formElement, dataModel, submitFunction);
            this.Forms[formElement.id] = newForm;
            return newForm;
        }

        public AddGrid(element: HTMLDivElement, gridOptions: any): GridView {
            var newGrid: TGridView = new TGridView(element, gridOptions);
            this.Grids[element.id] = newGrid;
            return newGrid;
        }
    }
}

Kann ich Objekte von einem generischen Typ erstellen?


75
2018-06-29 16:10


Ursprung


Antworten:


Da das kompilierte JavaScript alle Typinformationen gelöscht hat, können Sie nicht verwenden T ein Objekt neu erstellen.

Sie können dies auf nicht-generische Weise tun, indem Sie den Typ in den Konstruktor übergeben.

class TestOne {
    hi() {
        alert('Hi');
    }
}

class TestTwo {
    constructor(private testType) {

    }
    getNew() {
        return new this.testType();
    }
}

var test = new TestTwo(TestOne);

var example = test.getNew();
example.hi();

Sie könnten dieses Beispiel mithilfe von Generika erweitern, um die Typen zu straffen:

class TestBase {
    hi() {
        alert('Hi from base');
    }
}

class TestSub extends TestBase {
    hi() {
        alert('Hi from sub');
    }
}

class TestTwo<T extends TestBase> {
    constructor(private testType: new () => T) {
    }

    getNew() : T {
        return new this.testType();
    }
}

//var test = new TestTwo<TestBase>(TestBase);
var test = new TestTwo<TestSub>(TestSub);

var example = test.getNew();
example.hi();

49
2018-06-29 19:16



Um ein neues Objekt innerhalb eines generischen Codes zu erstellen, müssen Sie auf den Typ anhand seiner Konstruktorfunktion verweisen. Also anstatt das zu schreiben:

function activatorNotWorking<T extends IActivatable>(type: T): T {
    return new T(); // compile error could not find symbol T
}

Sie müssen dies schreiben:

function activator<T extends IActivatable>(type: { new(): T ;} ): T {
    return new type();
}

var classA: ClassA = activator(ClassA);

Siehe diese Frage: Generische Typ-Inferenz mit Klassenargument


87
2017-11-02 05:52



Alle Typinformationen werden in der JavaScript-Seite gelöscht und Sie können daher nicht wie T @ Sohnee neu T erstellen, aber ich hätte lieber einen Parameter eingegeben, der an den Konstruktor übergeben wurde:

class A {
}

class B<T> {
    Prop: T;
    constructor(TCreator: { new (): T; }) {
        this.Prop = new TCreator();
    }
}

var test = new B<A>(A);

15
2018-01-18 13:39



export abstract class formBase<T> extends baseClass {

  protected item = {} as T;
}

Sein Objekt kann beliebige Parameter empfangen, jedoch ist Typ T nur eine Typoskriptreferenz und kann nicht über einen Konstruktor erstellt werden. Das heißt, es werden keine Unterklassenobjekte erstellt.


7
2018-01-16 11:53



ich benutze das: let instance = <T>{}; es funktioniert im Allgemeinen EDIT 1:

export class EntityCollection<T extends { id: number }>{
  mutable: EditableEntity<T>[] = [];
  immutable: T[] = [];
  edit(index: number) {
    this.mutable[index].entity = Object.assign(<T>{}, this.immutable[index]);
  }
}

0
2017-10-03 15:07



Ich habe versucht, das Generische innerhalb einer Basisklasse zu instanziieren. Keines der obigen Beispiele funktionierte für mich, da sie einen konkreten Typ erforderten, um die Fabrikmethode zu nennen.

Nachdem ich eine Weile nachforschte und keine Lösung online fand, entdeckte ich, dass dies zu funktionieren scheint.

 protected activeRow: T = {} as T;

Die Stücke:

 activeRow: T = {} <-- activeRow now equals a new object...

...

 as T; <-- As the type I specified. 

Alle zusammen

 export abstract class GridRowEditDialogBase<T extends DataRow> extends DialogBase{ 
      protected activeRow: T = {} as T;
 }

0
2017-10-09 22:54