TypeScript-相互依赖修饰符

TypeScript-相互依赖修饰符,typescript,Typescript,从打字稿 因此,在评估多个项目时,将执行以下步骤 TypeScript中单个声明上的装饰器: 每个装饰器的表达式从上到下进行计算。 然后将结果作为从底部到顶部的函数调用 问题 我有两个装饰师,其中一个装饰师依赖另一个: 示例 @test() @testCase({...}) public doSomething(): void { } @testCase()依赖于@test(),因为在将测试用例添加到测试之前,需要将测试添加到测试运行程序中 我可以 @testCase({...}) @test

从打字稿

因此,在评估多个项目时,将执行以下步骤 TypeScript中单个声明上的装饰器:

  • 每个装饰器的表达式从上到下进行计算。
  • 然后将结果作为从底部到顶部的函数调用
  • 问题

    我有两个装饰师,其中一个装饰师依赖另一个:

    示例

    @test()
    @testCase({...})
    public doSomething(): void {
    }
    
    @testCase()
    依赖于
    @test()
    ,因为在将测试用例添加到测试之前,需要将测试添加到测试运行程序中

    我可以

    @testCase({...})
    @test()
    public doSomething(): void {
    }
    
    但在声明某个东西是测试之前声明测试用例似乎有些奇怪


    有没有办法让装饰器相互依赖,即
    testCase
    必须在
    test
    之后出现?

    您可以在
    testCase
    中向目标函数添加额外信息,然后在
    test
    装饰器中检查额外信息。在额外信息的下面是一个回调,更多的装饰者可以对此做出贡献。这提供了很大的灵活性,但是您可以添加其他信息而不是回调,并在
    测试中使用这些信息

    interface IAfterTestRegistered {
        afterTestRegisteredCallback?: ()=> void
    }
    // We could potentially have more then one contributor that need a callback executed.
    function addCallback(obj: IAfterTestRegistered, callback : () => void) {
        let oldCallback = obj.afterTestRegisteredCallback;
        if(oldCallback != undefined) {
            obj.afterTestRegisteredCallback = () =>{
                oldCallback();
                callback();
            }
        }
        else{
            obj.afterTestRegisteredCallback = callback;
        }
    }
    
    function test() : MethodDecorator {
        return function<T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) : void {
            console.log("test");
            let targetFunction: IAfterTestRegistered = target[propertyKey];
            if(targetFunction.afterTestRegisteredCallback) {
                targetFunction.afterTestRegisteredCallback();
            }
        }
    }
    
    function testCase(data: { index: number}) : MethodDecorator {
        return function<T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) : void {
            console.log(`testcase ${data.index}`);
            addCallback(target[propertyKey], () =>
            {
                console.log(`after-register testcase ${data.index}`);
            });
        }
    }
    
    class myClass {
        @test()
        @testCase({ index: 1 })
        @testCase({ index: 2 })
        public doSomething(): void {
        }
    }
    // Will output
    // testcase 2
    // testcase 1
    // test
    // after-register testcase 2
    // after-register testcase 1
    
    接口IAfterTestRegistered{
    后注册回调?:()=>无效
    }
    //我们可能有多个参与者需要执行回调。
    函数addCallback(obj:IAfterTestRegistered,callback:()=>void){
    设oldCallback=obj.afterestregisteredcallback;
    if(oldCallback!=未定义){
    obj.afterestRegisteredCallback=()=>{
    oldCallback();
    回调();
    }
    }
    否则{
    obj.afterestRegisteredCallback=回调;
    }
    }
    函数测试():MethodDecorator{
    返回函数(目标:对象,属性key:string |符号,描述符:TypedPropertyDescriptor):void{
    控制台日志(“测试”);
    let targetFunction:IAfterTestRegistered=target[propertyKey];
    if(targetFunction.AfterestRegisteredCallback){
    targetFunction.afterTestRegisteredCallback();
    }
    }
    }
    函数testCase(数据:{index:number}):MethodDecorator{
    返回函数(目标:对象,属性key:string |符号,描述符:TypedPropertyDescriptor):void{
    log(`testcase${data.index}`);
    addCallback(目标[propertyKey],()=>
    {
    log(`after register testcase${data.index}`);
    });
    }
    }
    类myClass{
    @测试()
    @testCase({index:1})
    @testCase({index:2})
    公共doSomething():无效{
    }
    }
    //将输出
    //测试用例2
    //测试用例1
    //试验
    //在寄存器测试用例2之后
    //在寄存器测试用例1之后
    
    这是针对您正在编写的库,还是仅针对您正在使用的库?@Fenton针对我正在编写的库。或者,您可以删除decorator的副作用,只使用有关方法的元数据对类进行注释。然后(在其他地方)在运行时检查类中的所有元数据并相应地进行操作。可以更好地扩展到相互依赖的多个装饰器。@ChrisDevereux,没错,这也是一个不错的选择。您可以随意添加它作为一个答案:)为什么不将两个decorator组合成一个并使用它呢?