I got an abstract superclass A
which is extended by implementations B
and C
.
In this superclass, I'd like to use method overloading to change the return type depending on whether a parameter is given or not.
The key is that this method returns "this", so that I can use method chaining.
I got this:
abstract class A {
abstract doSomething(a: string): Promise<A>;
abstract doSomething(a: string, b: number): A;
}
class B extends A {
async doSomething(a: string): Promise<A> {
console.log(a);
return this;
}
}
class C extends A {
doSomething(a: string, b: number): A {
console.log(a, b);
return this;
}
}
Unfortunately the implementations of both C and B have an error that read:
TS2416: Property 'doSomething' in type 'C' is not assignable to the same property in base type 'A'.
Type '(a: string, b: number) => A' is not assignable to type '{ (a: string): Promise<A>; (a: string, b: number): A; }'.
And both return statements have the error:
TS2322: Type 'this' is not assignable to type 'A'.
Type 'C' is not assignable to type 'A'.
Types of property 'doSomething' are incompatible.
Type '(a: string, b: number) => A' is not assignable to type '{ (a: string): Promise<A>; (a: string, b: number): A; }'.
Is it even possible to do this?
Thanks,
Eduardo
Nevermind, I found a way:
abstract class A<T = undefined | number> {
abstract doSomething(a: string, b: T): T extends undefined ? Promise<A> : A;
}
class B implements A<undefined> {
async doSomething(a: string): Promise<A> {
console.log(a);
return this;
}
}
class C extends A<number> {
doSomething(a: string, b: number): A {
console.log(a, b);
return this;
}
}
Seems a bit convoluted, but does the job. Please post another answer still if you know of a better way.
Hope it helps someone out there!