У меня проблема с обновлением контекста this
для методов объекта, переданного в качестве аргумента.
function decorate<T extends {
[K in keyof T]: T[K] extends (this: infer This, ...args: infer Args) => infer Return
? (this: This & { abc: 10 }, ...args: Args) => Return
: never;
}>(object: T) {
// @ts-ignore: just a hack to show a simple example
object.abc = 10;
return object;
}
decorate({
getString() { return "abc"; },
doSomething() {
const str: string = this.getString(); // Property 'getString' does not exist on type '{ abc: 10; }'.(2339)
const abc: number = this.abc;
}
});
TypeScript обнаружен abc
правильно, но потерял доступ к исходному контексту. Если копнуть глубже, выясняется, что предполагаемый This
равен unknown
:
function decorate<T extends {
[K in keyof T]: T[K] extends (this: infer This, ...args: infer Args) => infer Return
? (this: This, ...args: Args) => Return
: never;
}>(object: T) {
// @ts-ignore: just a hack to show a simple example
object.abc = 10;
return object;
}
decorate({
getString() { return "abc"; },
doSomething() {
const str: string = this.getString(); // Object is of type 'unknown'. (2571)
const abc: number = this.abc; // Object is of type 'unknown'. (2571)
}
});
Я пытался напрямую использовать исходный объект в качестве контекста, но T
в этот момент определяется только как объект ({}
), с неизвестными свойствами:
function decorate<T extends {
[K in keyof T]: T[K] extends (...args: infer Args) => infer Return
? (this: T, ...args: Args) => Return
: never;
}>(object: T) {
// @ts-ignore: just a hack to show a simple example
object.abc = 10;
return object;
}
decorate({
getString() { return "abc"; },
doSomething() {
const str: string = this.getString(); // Property 'getString' does not exist on type '{}'. (2339)
const abc: number = this.abc; // Property 'abc' does not exist on type '{}'. (2339)
}
});
Есть ли способ настроить контекст методов переданного объекта, или, может быть, есть совершенно другой способ добиться аналогичного эффекта?