Reputation: 6025
Here is some typescript code:
class ClassA<T extends BlueItem = BlueItem> {
protected _list: Array<T>;
get list(): Array<T> {
return this._list;
}
}
class ClassB<T extends GreenItem = GreenItem> extends ClassA<T> {
constructor() {
super();
this._list.push(new GreenItem());
}
}
class BlueItem {
protected blueItemProperty: number;
}
class GreenItem extends BlueItem {
protected greenItemProperty: number;
}
Compiler says "Argument of type 'GreenItem' is not assignable to parameter of type 'T'. What would be a correct approach to solve this?
Upvotes: 2
Views: 2821
Reputation: 15089
The issue is that you can't generate the correct types (T) inside your class, because you don't know what T is. Since you don't want to pass a factory function into your class, the next best solution would be to use union types and allow both types, like this:
class ClassA<T = BlueItem> {
protected _list:Array<T | BlueItem>;
get list(): Array<T | BlueItem> {
return this._list;
}
}
class ClassB<T = GreenItem> extends ClassA<T | GreenItem> {
}
class ClassC extends ClassB<RedItem> {
}
However, here you'd need to check the items from the list to be the right type.
Upvotes: 1
Reputation: 2848
Cast the GreenItem
to T
.
class ClassB<T extends GreenItem = GreenItem> extends ClassA<T> {
constructor() {
super();
this._list.push(<T>new GreenItem());
}
}
Upvotes: 1
Reputation: 22352
A simple way to solve the problem would be to make constructor of the list items also "generic":
class ClassB<T extends GreenItem = GreenItem> extends ClassA<T>
{
constructor(listItemCtor: {new(): T})
{
super();
const t = new listItemCtor();
this._list.push(t);
}
}
Its not universal solution - but if applicable - it will help.
As an option you can also drop generics altogether in the base class:
class ClassA
{
protected _list: Array<any>;
}
class ClassB<T extends GreenItem = GreenItem> extends ClassA
{
constructor()
{
super();
this._list.push(new GreenItem());
}
get list(): Array<T>
{
return this._list;
}
}
You will not loose much as you still have type checking on public properties of ClassB. And _list
is internal.
Upvotes: 2