【问题标题】:TypeScript method decorator -- `this` with noImplicitThis enabledTypeScript 方法装饰器——启用 noImplicitThis 的 `this`
【发布时间】:2019-05-19 02:59:15
【问题描述】:

我正在尝试编写一个简单的方法装饰器,在调用原始方法之前执行一些简单的逻辑。我能找到的所有示例都归结为最后调用originalMethod.apply(this, args) - 但是在tsconfig.json 中启用noImplicitThis,我收到以下错误:

[eval].ts(1,224): error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation.

我尝试通过调用originalMethod.apply(this as any, args) 解决问题,但错误仍然存​​在。

问题:是否有任何变通方法可以调用原始方法,无需为整个项目禁用noImplicitThis


最小示例 -- 与 noImplicitAny 禁用:

function logBeforeCall1(): originalMethodDecorator {
    return function(
        target: any,
        propertyKey: string | symbol,
        descriptor: PropertyDescriptor,
    ): PropertyDescriptor {
        const originalMethod = descriptor.value;
        descriptor.value = (...args: any[]) => {
            console.log('hello!');
            return originalMethod.apply(this, args);
        };
        return descriptor;
    };
}

class Test1 {
    private num: number = 1;

    @logBeforeCall1()
    test(next: number): void {
        console.log(this.num, '->', next);
        this.num = next;
    }
}

  • 我已经知道装饰器无法访问特定的对象实例(参见例如this question),但在上面的示例中使用this 可以工作
  • 装饰器的官方文档使用我示例中的构造(参见Property Decorators section),所以它有效,但与noImplicitThis 编译器选项冲突...

【问题讨论】:

    标签: typescript decorator typescript-decorator


    【解决方案1】:

    感谢@Grassator 的启发——这是一个有效的版本。不过,我不相信这可以在 TypeScript 的当前状态下安全地完成。

    function logBeforeCall2(): originalMethodDecorator {
        return function(
            target: any,
            propertyKey: string | symbol,
            descriptor: PropertyDescriptor,
        ): PropertyDescriptor {
            const originalMethod = descriptor.value;
            descriptor.value = function(this: any, ...args: any[]): any {
                console.log('hello!');
                return originalMethod.apply(this, args);
            };
            return descriptor;
        };
    }
    

    ...

    > t2.test(5)
    hello!
    1 '->' 5
    

    【讨论】:

      【解决方案2】:

      我认为你不能真正获得类型安全,但如果你只是想摆脱类型错误,你可以明确地说this: any(第 3 行):

      function logBeforeCall1() {
        return function (
          this: any,
          target: any,
          propertyKey: string | symbol,
          descriptor: PropertyDescriptor,
        ): PropertyDescriptor {
          const originalMethod = descriptor.value;
          descriptor.value = (...args: any[]) => {
            console.log('hello!');
            return originalMethod.apply(this, args);
          };
          return descriptor;
        };
      }
      

      【讨论】:

      • 这编译,但在运行时失败:` test(next) { console.log(this.num, '->', next); this.num = 下一个; }` -> TypeError: Cannot read property 'num' of undefined at test ([eval].ts:5:35)
      • 但是,受您回答的启发,我找到了一个解决方案——需要将 this 参数添加到实际的替换方法中,而不是装饰器函数中。
      猜你喜欢
      • 2019-10-04
      • 1970-01-01
      • 1970-01-01
      • 2018-01-31
      • 2020-01-11
      • 2017-04-11
      • 2019-11-12
      • 2021-10-10
      • 2021-09-28
      相关资源
      最近更新 更多