Return type `this` is spoiled when argument is generic

Issue

Here is the code: playground

class Smth {
    public self(): this {
        return this
    }

    public add() {
        return this as this & { func(): Smth }
    }
}

function f(x: Smth) {
    const y = x.add()    // Smth & { func(): Smth; }
    y.func()             // Ok
    const z = y.self()   // Smth & { func(): Smth; }
    z.func()             // Ok
}

function g<S extends Smth>(x: S) {
    const y = x.add()    // S & { func(): Smth; }
    y.func()             // Ok
    const z = y.self()   // S
    z.func()             // Error: Property 'func' does not exist on type 'S'.
}

Functions f and g have the only difference that the second one is generic:

function f(x: Smth) {
function g<S extends Smth>(x: S) {

But by some reason they start to behave differently on the line

const z = y.self()

Method self is declared as returning this and it works fine in non-generic function (z becomes Smth & { func(): Smth; }). But in generic function by some reason z gets just S instead of S & { func(): Smth; }.

What should I write to get a correct type S & { func(): Smth; } after call y.self() in the generic function?

Solution

You can do it, but not with polymorphic this. It works if you make self generic and have this inferred at call site.

class Smth {
    public self(): this {
    //public self<T>(this:T): T {
        return this
    }

    public add() {
        return this as this & { func(): Smth }
    }
}

function f(x: Smth) {
    const y = x.add()    // Smth & { func(): Smth; }
    y.func()             // Ok
    const z = y.self()   // Smth & { func(): Smth; }
    z.func()             // Ok
}

function g<S extends Smth>(x: S) {
    const y = x.add()    // S & { func(): Smth; }
    y.func()             // Ok
    const z = y.self()   // S
    z.func()             // Error: Property 'func' does not exist on type 'S'.
}

Playground Link

Not sure why polymorphic this doesn’t work in this case. I believe it should you might want to file an issue on GitHub.

Answered By – Titian Cernicova-Dragomir

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published