2017-02-25 7 views
2

Ich habe in dem Erstellen von Klassen aus Strings in Javascript suchen, bis ich auf diese kam:in Typoskript/Angular2

var instance = new window[classString](); 

Dies ist jedoch nicht, da es in Maschinenschrift, zu funktionieren scheint ist Typinformation fehlt.

Details:

interface SomeInterface{ 
    structuredData: any; 
} 

class A implements SomeInterface { 

} 

ich in einer Datenbank JSON serialisiert Klasseninformationen bin zu speichern. Nehmen wir an, ich habe eine Modellklasse A, die Eigenschaften dieser Klasse werden als JSON-Zeichenfolge im Frontend serialisiert und zusammen mit dem Klassennamen, der diese Daten darstellt, an die Datenbank gesendet, d. H. Die Datenbank enthält eine class_type-Spalte, die den Namen der Klasse enthält. In diesem Fall wäre das die Zeichenfolge "A". Nun möchte ich diese Daten in meine Anwendung zurückholen und dynamisch eine Instanz aus diesen Daten konstruieren.

Wenn wir die Javascript Instanziierung Code sehe ich oben gefunden, würde ich gerne so etwas wie dies zu tun:

let instance = new window['A'](); 
instance.structuredData = foo; 

Da diese Klassen generische Parameter enthalten, die auf eine bestimmte Schnittstelle haften ich wäre in der Lage zu zuweisen die serialisierten Daten zu diesen neu instanziierten Instanzen.

Ich benutze Angular2/Webpack und würde wirklich alle Hinweise, wie dies zu tun ist.

Wenn Sie den Code verwenden, wie ich oben erwähnt, erhalte ich die folgende Compiler-Fehler:

Cannot use 'new' with an expression whose type lacks a call or construct signature.

Wenn ich versuche, die strenge Typprüfung zu umgehen, indem

mit
declare var window; 

ich folgende Fehlermeldung erhalten :

window['classString'] is not a constructor

+0

Welche Fehler Sie mit Ihrem Typoskript Code erhalte? –

+0

@MichaelLiu Fehlermeldung hinzugefügt. –

+0

Ich kann den Fehler nicht reproduzieren. Wenn ich 'instance = new window ['A']();' in eine Standalone-.ts-Datei lege, kompiliert es sich gut. –

Antwort

2

Da Angular2 die Beteiligung von Webpack gekonnt abstrahiert, weiß ich nicht kn genau wie Module im Detail geladen und verarbeitet werden. Meine Vermutung (wie in den Kommentaren erwähnt) ist jedoch, dass die Klasse im Fenster/globalen Raum nicht verfügbar ist, daher habe ich eine Lösung gefunden, die korrekt sein könnte (ausprobiert und funktioniert, aber nicht sicher, ob das korrekt ist) Weg, um diese Art der Sache zu tun):

// first I require the module that is named in snake case with a .ts 
// suffix based on the string that is stored in the database 
// so if the stored string is SomeThing, we require the file 
// called 'some_thing.ts'. Note: using lodash to generate that string 
const dynModule = require('./' + _.snakeCase(classTypeString)); 

// next, we get the constructor by the class name from that module 
// which is exactly the string that we stored in the db 
const klass = dynModule[classTypeString]; 

// now we have the constructor function of the class and can 
// instantiate a new class from that 
let instance: SomeInterface = new klass(); 

instance.structuredData = foo; 
+0

Der Fehler in der Frage ist spezifisch für Typescript und Tippfehler. – estus

0

Sie diese Klassen selbst in dem Fenster Objekt setzen könnte, auch wenn Sie in anderen Klassen sind:

(window as any).example = class {}; // replace with you class 
// and then later in code.... 
const classNameStr = 'example'; 
const init = new window[classNameStr](); 

wenn Sie nicht gerne Schreibe innerhalb des Fensterobjekts, du könntest sie stattdessen in einem Objekt/Wörterbuch irgendwo in deinem Code speichern. Oder einfach Eval verwenden (wenn es nicht eine gute Praxis, es zu benutzen):

eval(`new ${className}()`);