从Typescript / Angular2

时间:2017-02-25 16:20:04

标签: javascript angular typescript webpack

我一直在寻找从Javascript中的字符串创建类,直到我遇到这个:

var instance = new window[classString]();

但是,这似乎不适用于Typescript,因为缺少类型信息。

详细信息:

interface SomeInterface{
  structuredData: any;
}

class A implements SomeInterface {

}

我将JSON序列化类信息存储在数据库中。假设我有一个模型类A,该类的属性在前端被序列化为JSON字符串,并与表示此数据的类名一起发送到数据库,即数据库包含一个class_type列,其中包含类的名称。在这种情况下,这将是字符串' A'。现在,我想将这些数据恢复到我的应用程序中,并从该数据动态构造实例。

如果我们查看上面找到的Javascript实例化代码,我很乐意做这样的事情:

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

由于这些类包含遵循某个接口的通用参数,因此我可以将序列化数据分配给那些新实例化的实例。

我正在使用Angular2 / Webpack,并且非常感谢有关如何执行此操作的任何提示。

当使用上面提到的代码时,我得到以下编译器错误:

  

不能使用' new'表达式类型缺少调用或   构建签名。

如果我尝试使用

规避严格的类型检查
declare var window;

我收到以下错误:

  

window [' classString']不是构造函数

2 个答案:

答案 0 :(得分:2)

由于Angular2巧妙地抽象了Webpack的参与,因此我并不确切知道如何加载和处理模块。但是,我的猜测(正如评论中所提到的)该类在窗口/全局空间中不可用,因此我提出了一个可能正确的解决方案(尝试过并且有效,但不确定是否这样做&#39 ; s是做这种事情的正确方法):

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

答案 1 :(得分:1)

您可以自己将这些类放在窗口对象中,即使您在其他类中也是如此:

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

如果您不想在窗口对象内写入,则可以将它们存储在代码中的某个对象/字典中。 或者只是使用Eval(尽管使用它并不是一个好习惯):

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