Home > Blockchain >  Can a typescript function return an object extended with another object whose functions `this` is th
Can a typescript function return an object extended with another object whose functions `this` is th

Time:01-05

Is there a way to make typescript understand a recursive this type? I want to type up some working JavaScript that allows extending a base object with extra functions. What I've got currently looks like this:

interface ThingBase {
  method(): string;
  data: string;
}

function makeThing<
  Ext extends {[index:string]: (this: ThingBase & Ext, ...args:any[]) => any}
>(extension: Ext): ThingBase & Ext {
  return {
    ...extension,
    method() { return "hello" },
    data: "yes"
  }
}

const thingWithExt = makeThing({
  yello: function() {
    return this.data; // works
  },
  mmm: function() {
    return this.yello(); // does not work
  }
});

const d = thingWithExt.yello();

But this doesn't work, it errors on the function names with Index signature for type 'string' is missing in type 'ThingBase'

If I remove & Ext from the this type then it works in that the extension functions can access the base functions, but they cannot access other extension functions.

Here's a playground with a slightly modified version that TS accepts but still does not type correctly: Playground Link

CodePudding user response:

You can use ThisType to signal to TypeScript what this is supposed to be inside an object literal.

function makeThing<
    Ext extends Record<keyof Ext, (...a: any[]) => any>
>(extension: Ext & ThisType<Ext & ThingBase > ): ThingBase & Ext {
    return {
        ...extension,
        method() { return "hello" },
        data: "yes"
    }
}

const thingWithExt = makeThing({
    yello: function () {
        return this.data; // works
    },
    mmm: function () {
        return this.yello(); // also ok
    },
    te() {
        return this.mmm();
    }
});

Playground Link

  • Related