作为装饰器do not mutate the types of the things they decorate (see microsoft/TypeScript#4881),使用装饰器基本上不可能做到这一点。因此,即使您在修饰带有string
参数的方法时,即使您在运行时进行了更改,编译器仍会将其视为带有string
参数的方法。 microsoft / TypeScript#4881中对此进行了大量讨论,双方都怀有强烈的感情,但最终unlikely anything will change in TypeScript直到the analogous proposed JavaScript feature成熟到足以稳定为止。
相反,您可能想考虑使用类似装饰器的函数,该函数使用一个方法接收类构造函数,然后使用增强方法将其转换为另一个类构造函数。它就像一个装饰器,因为您没有将其与@
表示法一起使用;相反,您可以像class expression和subclass一样使用它。用类表达式替换 class 装饰器更为简单,但是您也可以使用方法装饰器来做一些工作。
这是一个例子。请注意,以下代码只是一个示例。它尚未经过全面测试,并且在所有情况下都可能无法达到您的期望。为了安抚编译器,它进行了大量类型杂耍和类型断言:
type AugmentMethod<
T extends Record<K,(...args: any) => any>,K extends keyof T,A extends readonly any[]> = { [P in keyof T]:
P extends K ? (...args: A) => ReturnType<T[P]> : T[P]
};
function AugmentMethod<
C extends new (...args: any) => Record<K,T extends InstanceType<C>,K extends keyof any,A extends readonly any[],>(
ctor: C,methodName: K,wrapMethod: (...args: A) => Readonly<Parameters<T[K]>>
) {
return class extends (ctor as any) {
constructor(...args: any) {
super(...args);
}
[methodName](...args: A) {
return super[methodName](...(wrapMethod(...args) as any[]));
}
} as (new (...args: ConstructorParameters<C>) => AugmentMethod<T,K,A>) &
{ [P in keyof C]: P extends "prototype" ? AugmentMethod<T,A> : C[P] };
}
因此类型AugmentMethod
具有三个类型参数:“基”类实例类型T
,该类的方法名称K
和新参数列表类型{{1 }}。它返回“子”类实例类型的类型,其属性与A
的属性相同,除了名为T
的方法采用类型为K
的参数外。
函数A
具有三个参数:“基”类构造函数值,该值构造类型为AugmentMethod
的实例,方法名称为类型T
为该类提供了一个参数包装函数,该包装函数接受K
类型的参数并返回要传递给“基本”类构造函数的参数的有序数组。然后,它返回一个实例为A
的“子”类构造函数:与“基本”实例相同,不同之处在于其扩展方法希望将一组参数传递给上面的参数包装函数。
这类似于您的示例代码:
AugmentMethod<T,A>
因此class AppComponent {
name = "Angular";
decorated(data: { data: string }) {
console.log("Got " + JSON.stringify(data));
return data.data;
}
replacedMethod(val: string) {
console.log(val);
return val;
}
}
const a = new AppComponent();
const sa = a.decorated({ data: "hi" }); // Got {"data":"hi"};
console.log(sa); // hi
类保持不变,并且其AppComponent
方法期望使用类型为decorated()
的参数。让我们使用{data: string}
类表达式:
AugmentMethod
因此,您可以看到class WrappComponent extends
AugmentMethod(AppComponent,"decorated",(data: string) => [{ data }] as const) { }
const w = new WrappComponent();
const sw = w.decorated("hey"); // Got {"data":"hey"};
console.log(sw); // hey
的行为类似于WrappComponent
的版本,其AppComponent
方法已被decorated()
函数“修饰”。
好的,希望能有所帮助;祝你好运!
Link to code
本文链接:https://www.f2er.com/3010950.html