在 TS 中为 long class 定义动态装饰器而无需重新定义所有方法的方法
Way to define dynamic decorator in TS for long class without redefinition of all methods
我有一个 class,里面有很多方法。我们先不关注这里,可能这个 class 可能会被重构和重写为几个 classes,因为它最终会是,但不知道。我想要装饰器,它只装饰这个 class 的一种方法。我们可以通过多种方式做到这一点。
Class接口:
interface IFoo {
method1 (): number;
method2 (a: string): number;
method3 (b: IFoo): number;
method4 (c: string | (() => string)): number;
method5 (d: number, e: string): number;
}
Classical OOP解决方案:定义重新定义特定方法的装饰器,并为所有其他方法调用超级实现。像这样。
class FooDecorator implements IFoo {
constructor (
private readonly provider: IFoo
) {}
public method1 (): number {
return this.provider.method1() + 1;
}
public method2 (a: string): number {
return this.provider.method2.apply(this.provider, arguments);
}
public method3 (b: IFoo): number {
return this.provider.method3.apply(this.provider, arguments);
}
public method4 (c: string | (() => string)): number {
return this.provider.method4.apply(this.provider, arguments);
}
public method5 (d: number, e: string): number {
return this.provider.method5.apply(this.provider, arguments);
}
}
如你所见,相当长的编写和代码重复。
尝试利用一些 JS 功能。
interface IFooDecorator {
method1: IFoo["method1"];
}
class FooDecorator implements IFooDecorator {
constructor (
private readonly provider: IFoo
) {
Object.setPrototypeOf(this, provider);
}
public method1 (): number {
return this.provider.method1() + 1;
}
}
明显的缺点是错误的类型化和 setPrototypeOf 的使用
我也尝试过使用 Proxy,但对使用代理的类型的支持也很差。还有其他解决方案吗?第一种方法很好,以防我们可以使用 .apply
调用自动重新定义非装饰方法。
将装饰器实现为使用 Object.create
而不是 class
语法的工厂函数,这样您就不需要使用 Object.setPrototypeOf
:
function fooDecorator<T>(provider: IFoo): T implements IFoo {
return Object.create(provider, {
method1: {
value(): number {
return provider.method1() + 1;
},
writable: true,
configurable: true
}
});
}
我有一个 class,里面有很多方法。我们先不关注这里,可能这个 class 可能会被重构和重写为几个 classes,因为它最终会是,但不知道。我想要装饰器,它只装饰这个 class 的一种方法。我们可以通过多种方式做到这一点。
Class接口:
interface IFoo {
method1 (): number;
method2 (a: string): number;
method3 (b: IFoo): number;
method4 (c: string | (() => string)): number;
method5 (d: number, e: string): number;
}
Classical OOP解决方案:定义重新定义特定方法的装饰器,并为所有其他方法调用超级实现。像这样。
class FooDecorator implements IFoo { constructor ( private readonly provider: IFoo ) {} public method1 (): number { return this.provider.method1() + 1; } public method2 (a: string): number { return this.provider.method2.apply(this.provider, arguments); } public method3 (b: IFoo): number { return this.provider.method3.apply(this.provider, arguments); } public method4 (c: string | (() => string)): number { return this.provider.method4.apply(this.provider, arguments); } public method5 (d: number, e: string): number { return this.provider.method5.apply(this.provider, arguments); } }
如你所见,相当长的编写和代码重复。
尝试利用一些 JS 功能。
interface IFooDecorator { method1: IFoo["method1"]; } class FooDecorator implements IFooDecorator { constructor ( private readonly provider: IFoo ) { Object.setPrototypeOf(this, provider); } public method1 (): number { return this.provider.method1() + 1; } }
明显的缺点是错误的类型化和 setPrototypeOf 的使用
我也尝试过使用 Proxy,但对使用代理的类型的支持也很差。还有其他解决方案吗?第一种方法很好,以防我们可以使用 .apply
调用自动重新定义非装饰方法。
将装饰器实现为使用 Object.create
而不是 class
语法的工厂函数,这样您就不需要使用 Object.setPrototypeOf
:
function fooDecorator<T>(provider: IFoo): T implements IFoo {
return Object.create(provider, {
method1: {
value(): number {
return provider.method1() + 1;
},
writable: true,
configurable: true
}
});
}