Reputation: 18513
I have a class that has several functions that return a new instance of itself and I want to extend the class and have those functions return an instance of the child class instead. e.g.
class A {
constructor(public val) {
}
getAnother(val): A {
return new A(val);
}
next(): A {
return this.getAnother(this.val + 1);
}
double(): A {
return this.getAnother(this.val * 2);
}
}
class B extends A {
getAnother(val): B {
return new B(val);
}
next(): B {
return <B>super.next();
};
double(): B {
return <B>super.double();
};
getValAsStr() {
return String(this.val);
}
}
let b = new B(1);
console.log(b.next().getValAsStr()); // logs "2"
This does what I am trying to accomplish but ideally I wouldn't need to reimplement next()
and double()
in class B
and manually cast the return type. I tried an approach using generics that lets me only override getAnother()
in class B but it breaks the polymorphic relationship between A and B
abstract class I<TResult> {
constructor(public val) {
}
abstract getAnother(val): TResult;
next(): TResult {
return this.getAnother(this.val + 1);
}
double(): TResult {
return this.getAnother(this.val * 2);
}
}
class A extends I<A> {
getAnother(val): A {
return new A(val);
}
}
class B extends I<B> {
getAnother(val): B {
return new B(val);
}
getValAsStr() {
return String(this.val);
}
}
Is there an approach that is cleaner than my first approach and that maintains the relationship between A and B in TypeScript?
Upvotes: 0
Views: 1051
Reputation: 53492
You can use a polymorphic this.
class A {
constructor(public val) {
}
getAnother(val): this {
return new A(val);
}
next(): this {
return this.getAnother(this.val + 1);
}
double(): this {
return this.getAnother(this.val * 2);
}
}
class B extends A {
getAnother(val): this {
return new B(val);
}
getValAsStr(): string {
return String(this.val);
}
}
(untested)
Upvotes: 1