简体   繁体   English

从类型实例化通用对象

[英]Instantiate generic object from type of

I found this code to instantiate a new object T with a parameter : 我发现以下代码使用参数实例化了一个新对象T:

create<T>(type: { new(p: any): T }, val: any): T {
    return new type(val);
  }

My goal is to have a base class which I can inherit to init my array properties : 我的目标是拥有一个可以继承以初始化数组属性的基类:

export class Base {
  create<T>(type: { new(p: any): T }, val: any): T {
    return new type(val);
  }

  init<T>(propertyArray: T[], input: any): void {
    if (propertyArray == null) {
      propertyArray = [];
      for (let i in input) {
        let tmpObj = this.create(T, i);
        propertyArray.push(tmpObj);
      }
    }
  }
}

class A extends Base {

  private _prop: B[];

  get prop() {
    return this._prop;
  }
  set prop(value: any) {
    this.init(this._prop, value);
  }

  constructor(obj: any) {
    super(obj);
    this.prop = obj && obj.item || null;
  }
}

But in this sample let tmpObj = this.create(T, i); 但是在此示例中, let tmpObj = this.create(T, i); I get this error : 我收到此错误:

'T' only refers to a type, but is being used as a value here. “ T”仅指类型,在此被用作值。

How can I correct this to work ? 我该如何纠正此问题?

Thank you 谢谢

I'm not sure how the rest of your code is supposed to work, but you have to pass in a constructor of a type to be able to construct an instance of the type. 我不确定其余代码的工作方式,但是您必须传入类型的构造函数才能构造该类型的实例。


Let's examine the signature of the create() function: 让我们检查一下create()函数的签名:

declare function create<T>(type: { new(p: any): T }, val: any): T;

This is a generic function that works for any type T the caller wants. 这是一个通用函数,适用于调用者想要的任何类型 T The (unfortunately named) type parameter is a constructor object that you call with new , and which returns a value of type T . (不幸地命名) type参数是您使用new调用的构造函数对象,它返回类型T的值。 It is an object that exists at runtime, not a type that exists only at design/compile time. 它是在运行时存在的对象 ,而不是仅在设计/编译时存在的类型

It is a confusing but useful practice to use the same name for a class constructor object and the type of an instance of the class: 对类构造函数对象使用相同的名称以及该类的实例的类型是一种令人困惑但有用的做法:

class Foo {};

This creates both a class constructor object named Foo that exists at runtime, and an instance type named Foo that exists at design time: 这将创建一个在运行时存在的名为Foo的类构造函数对象, 以及一个在设计时存在的名为Foo的实例类型:

const foo: Foo = new Foo();

The first Foo is the type, and the second Foo is the class constructor. 第一个Foo是类型,第二个Foo是类构造函数。 This gets transpiled into something like: 这被翻译成如下内容:

var foo = new Foo();

Notice that the type named Foo is completely gone, since it exists only at design time. 注意,名为Foo的类型已完全消失,因为它仅在设计时存在。 The point is: even though you often have constructor objects with the same name as types, they are not interchangeable. 关键是:即使您经常有与类型同名的构造函数对象,它们也不能互换。 A generic type parameter is a type, not a constructor object. 泛型类型参数是类型,而不是构造函数对象。


Okay now let's see what you're passing into create() : 好的,现在让我们看看您要传递给create()

this.create(T, i)

Hmm, what's T ? 嗯,什么T It's the type parameter of the generic init() method. 它是通用init()方法的类型参数。 So it is only the name of a design-time type, not the name of a runtime object. 因此,它只是设计时类型的名称,而不是运行时对象的名称。 This can never work. 这永远都行不通。 Instead, as above, you need to pass in a constructor object of the type { new(p: any): T } . 相反,如上所述,您需要传入{ new(p: any): T }类型的构造函数对象。 But you don't have one of those, unless you add it to the list of parameters to init() : 但是您没有其中之一,除非您将其添加到init()的参数列表中:

init<T>(ctor: { new(p: any): T }, propertyArray: T[], input: any): void {
  // ...
  this.create(ctor, i);
  // ...
}

Now it will compile, although you will have to pass in a constructor for B in your prop setter. 现在它将编译,尽管您必须在prop设置器中传入B的构造函数。 Not that I know what B is or if you have a constructor for it. 不是我知道B是什么,或者您是否有构造函数。 And not that I know why the init() method only does something if the propertyArray parameter is null , so that the prop setter can only work once. 并不是我知道为什么init()方法仅在propertyArray参数为null时才执行某些操作,以便prop设置器只能工作一次。 And not that I know why you enumerate the keys of input and use them as arguments to whatever constructor you have for B . 并不是我知道为什么您要枚举input键并将它们用作B任何构造函数的参数。 And... well, I'm obviously confused by the rest of your code. 而且...嗯,我显然对其余的代码感到困惑。 Suffice it to say that you need to pass in a constructor of T instead of T before you can proceed. 只需说您需要传递T而不是T的构造函数就可以继续。

Hope that helps; 希望能有所帮助; good luck. 祝好运。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM