Issue
how i can solve this issue with typescript ?
ex: When you have a class registers, and when you want creates a instances of all classes registered ?
export abstract class FooAbstract {
static registers: typeof FooAbstract[] = []; // a registers
static create<T extends FooAbstract>(constr: new ()=>T) {
return new constr();
}
}
export class A extends FooAbstract {
name:string;
}
FooAbstract.registers.push(A); // in my case i use decoration, but not matter !
// what should be the good way here ?
const test = FooAbstract.registers.map((cls)=> cls.create(cls))
Argument of type 'typeof FooAbstract' is not assignable to parameter of type 'new () => FooAbstract'.
Cannot assign an abstract constructor type to a non-abstract constructor type.ts(2345)
Solution
The issue is in this line (constr: new () => T) .
create static method expects a regular constructor, not an abstract constructr whereas you are trying to pass an abstract constructor to this method.
See here FooAbstract.registers.map((cls) => cls.create(cls)). cls.create expects new () => T but you are trying to use abstract new () => T.
You can add abstract flag/modifier to constr argument.
export abstract class FooAbstract {
static registers: typeof FooAbstract[] = [];
static create<T extends FooAbstract>(constr: abstract new () => T) { // add `abstract` modifier
return new constr();
}
}
const test = FooAbstract.registers.map((cls) => cls.create(cls))
But above approach, causes a new problem. You are not allowed to create an instance of abstract class, new constr() // <--- error is here.
UNSAFE APPROACH, MIGHT CAUSE AN ERROR IN RUNTIME. SEE @kaya3 COMMENTS
If you want to create an instance of some class, this class should not be an abstract.
Hence, we need to create an empty anonymous class which will extends our abstract class:
export abstract class FooAbstract {
static registers: typeof FooAbstract[] = [];
static create = <T extends FooAbstract>(constr: new () => T) => new constr()
}
const test = FooAbstract.registers.map((cls) =>
cls.create(class extends cls { }) // <--- anonymous class is just a wrapper
)
There is another one solution. You can just remove abstract keyword from FooAbstract class definition.
P.S. I'm not an OOP expert, so I can't say whether the answer I have provided meets OOP good practices or not. I have shown you just how to fix TS error
P.P.S if using abstract class or even OOP approach is not important for you, I can recommend another approach if you will provide more details to your question.
Answered By - captain-yossarian

0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.