Michael Tiller Michael Tiller - 26 days ago 6
TypeScript Question

Polymorphic this in TypeScript

I'm trying to do what I think is a "textbook" use case for polymorphic

this
and it isn't working and I just can't figure this out. Imagine I have some
abstract
base class that is cloneable, e.g.:

abstract class X {
abstract clone(): this;
}


Now I want to implement a base class that provides a
clone
implementation:

class Y extends X {
constructor(private x: number) { super() }
clone(): this { return new Y(this.x + 1); }
}


When I do this, I get an error that says
Type Y is not assignable to type 'this'
. I'm totally confused. All I want to convey here is the type constraint that if a subclass of
X
has its
clone
method invoked, that the type of the thing that you will get back will be identical to the subtype. Isn't this exactly what polymorphic
this
is for? What am I doing wrong here?

Here is a link to this code in the TypeScript playground.

Answer

No, as things are right now, it's not a supported use case for this type. A method with this return type should return an instance of derived class even if this method is not overridden in the derived class - see code in this answer for an example that justifies this.

In other words, given abstract clone(): this declaration, this code must be valid even if Z does not override clone itself, but you implementation of clone in Y breaks it.

class Z extends Y {
    f() {
        let c: Z = this.clone();
    }
}

So it looks like a method with this return type should always return this.

UPDATE: I found an open issue with this use case on github, marked as 'accepting pull requests'. I'm not sure however if they really intend to support it, or plan to fix cloneNode in their compiler in some other way.