在将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)
}
});
是否有一种方法可以调整传递对象方法的上下文,或者有完全不同的方法来实现类似的效果?
答案 0 :(得分:1)
我认为您最好的选择是使用ThisType
。这是编译器的特殊标记接口,可让您轻松指定this
的含义。将对象分配给键入为ThisType<T>
的位置时,对于在该对象中定义的任何方法/函数,T
被认为是this
的类型。
有了这个,解决问题的方法变得非常简单:
function decorate<T>(object: T & ThisType<T & { abc: number }>) {
return Object.assign( object, { abc: 10 });
}
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)
}
});