2016-06-06 2 views
1

Ich habe eine Anwendung, die durch Ausführen seiner Methode .init(params) wie folgt initialisiert:Wie ein Array mit Klassen in TypeScript eingeben?

app.init([TopBar, StatusBar, MainArea]); 

Wo TopBar, StatusBar und MainArea Klassen sind nicht Instanzen von Klassen. Jede dieser Klassen implementiert die gleiche Schnittstelle IComponent.

Ich möchte Objekte aus den übergebenen Klassen in der .init(params) Methode instanziiert, wie folgt aus:

init(params: IComponent[]): void { 
    params.map(function (component) { 
     let comp = new component(); 
     this.components[comp.constructor.name] = comp; 
    }, this); 

Das Problem ist, dass, da diese nicht Instanz sind, nicht Typoskript nicht ihre Typen kennen und wirft einen Fehler:

error TS2345: Argument of type '(typeof TopBar | typeof StatusBar | typeof MainArea)[]' is not assignable to parameter of type 'IComponent[]'.

Wie repariere ich den Code, so dass ich ein Array von Klassen übergeben könnte, die eine Schnittstelle zu einer Methode implementieren?

+0

Warum nicht eine Fabrik-Funktion verwenden, anstatt zu versuchen neu auf der Klasse zu benutzen? – davestevens

Antwort

1

Es gibt einen working typescript playground (führen Sie es mit Alarm zu bekommen)

, was wir brauchen, ist eine benutzerdefinierte type InterfaceComponent zu erstellen. Das wird als ein Array der init() Verfahren zu erwarten

interface IComponent { } 
class TopBar implements IComponent { } 
class StatusBar implements IComponent { } 
class MainArea implements IComponent { } 

// this is a type we want to be passed into INIT as an array 
type InterfaceComponent = (typeof TopBar | typeof StatusBar | typeof MainArea); 

class MyClass { 

    components: {[key:string] : IComponent } = {}; 

    init(params: (InterfaceComponent)[]): void { 
    params.map((component) => { 
     let comp = new component(); 
     this.components[comp.constructor["name"]] = comp; 
    }, this); 
    } 
} 

let x = new MyClass(); 
x.init([TopBar, StatusBar, MainArea]) 

alert(JSON.stringify(x.components)) 

prüft es here

+0

Dies ist die eleganteste Lösung, danke! Obwohl es bedeutet, dass ich, wenn ich viele Komponenten wie 100+ habe, alle zum Typ InterfaceComponent hinzufügen muss? –

+0

Nun, schwer zu sagen, ohne tiefer zu tauchen ... dem obigen Ansatz zu folgen ... wir müssten es erweitern ... und das ist nicht in Ordnung für 100+. Einige Factory-Methoden, die mit einem unbekannten Typ arbeiten (nicht so sicher), wären der richtige Weg zu gehen, würde ich sagen ... 'var instance = Object.create (objectType.prototype); instance.constructor.apply (instance, constructorParameters); ' –

+0

Die Vererbung ist falsch herum - InterfaceComponent muss alle Klassen kennen, die es implementieren, sicherlich ist das keine gute Sache? – davestevens

0

Vielleicht könnten Sie den Typ comp als InterfaceComponent angeben.

var comp: InterfaceComponent = new component(); 
this.components[comp.constructor.name] = comp; 
+1

Das letzte, was ich mit TypeScript machen möchte, ist, jedem Typ einen beliebigen Typ zuzuweisen. –

+0

Wie wäre es mit der Zuweisung? InterfaceComponent – fireydude

0

Verwenden Sie stattdessen eine Factory-Methode. Die Erklärung ist ein bisschen unbeholfen, aber die Idee funktioniert:

interface InterfaceComponent { 
    name: string; 
} 

class TopBar implements InterfaceComponent { 
    name: string; 
} 

class StatusBar implements InterfaceComponent { 
    name: string; 
} 

class MainArea implements InterfaceComponent { 
    name: string; 
} 

interface InterfaceComponentFactory { 
    create:() => InterfaceComponent; 
} 

function init(params: InterfaceComponentFactory[]): void { 
    params.map(function (component) { 
     let comp = component.create(); 
     this.components[comp.name] = comp; 
    }, this); 
} 

init([{ create:() => new TopBar() }, { create:() => new StatusBar() }, { create:() => new MainArea() }]); 
Verwandte Themen