I have a function that takes an object of other functions:
const fn = <T extends Record<string, (...args: any) => Promise<unknown>>>(
t: T
) => {
// code for binding `this` context for `t` variable methods.
};
I would like to extend this
context of methods passed to fn
with a few properties having the ability to access other methods from this
at the same time (foo
and bar
in the example):
fn({
async foo() {},
async bar() {
this.foo // should reference foo function
this.propertyA // should point to custom bound property
},
});
I've tried something like that, but T
seems to be unknown
when used inside of its own definition, so original context is lost and I have only { propertyA: string }
as this
type:
const fn = <
T extends Record<
string,
(this: T & { propertyA: string }, ...args: any) => Promise<unknown>
>
>(
t: T
) => {};
fn({
async foo() {},
async bar() {
this.foo // not available
this.propertyA // available
},
});
CodePudding user response:
To get the sort of inference you're looking for, you need to use the special "magical"/intrinsic ThisType<T>
utility type:
const fn = <T extends Record<keyof T, (...args: any) => Promise<unknown>>>(
t: T & ThisType<T & { propertyA: string }>
) => { };
fn({
async foo(x: number) { },
async bar() {
this.foo(3) // this works
this.propertyA.toUpperCase(); // this too
},
});
Your version, with a this
parameter, ends up requiring that the methods have such a this
context, but does not infer it. Whereas ThisType<T>
produces a contextual type for methods in which this
is inferred how you want. And note that ThisType<T>
is "magical"; it is granted this inference behavior by the compiler itself and can't be re-implemented by user code.