I found this code to instantiate a new object T with a parameter :
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);
I get this error :
'T' only refers to a type, but is being used as a value here.
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:
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. The (unfortunately named) type
parameter is a constructor object that you call with new
, and which returns a value of type 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:
const foo: Foo = new Foo();
The first Foo
is the type, and the second Foo
is the class constructor. 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. 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()
:
this.create(T, i)
Hmm, what's T
? It's the type parameter of the generic init()
method. 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 }
. But you don't have one of those, unless you add it to the list of parameters to 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. Not that I know what B
is or if you have a constructor for it. 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. And not that I know why you enumerate the keys of input
and use them as arguments to whatever constructor you have for 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.
Hope that helps; good luck.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.