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();
}
});