【问题标题】:TypeScript decorator declaration that implements an interface实现接口的 TypeScript 装饰器声明
【发布时间】:2017-04-18 00:38:12
【问题描述】:

我尝试了几种不同的方法来在 TypeScript 中声明一个装饰器函数,以便被装饰的类实现一个接口。像这样的:

interface IValidatable {
    checkValidation: () => boolean;
}

function validated<T>(Class: {new():T}): {new():T & IValidatable} {
    Class.prototype.checkValidation = () => true;
    return Class as {new():T & IValidatable};
}

鉴于上述情况,我希望我可以做这样的事情:

@validated
class Foo {

}

let f = new Foo();
let isValid = f.checkValidation();

但最后一行被标记为错误(“类型 'Foo' 上不存在属性 'checkValidation'。”)。

以下确实在不产生错误的意义上起作用:

let ValidatedFoo = validated(Foo);
let vf = new ValidatedFoo();
let isValid2 = vf.checkValidation();

有没有办法制定装饰器声明,使第一个用法示例不会产生错误?

【问题讨论】:

标签: typescript


【解决方案1】:

我不认为你可以修复它,以便装饰器改变编译器对 Foo 类的看法。
装饰器在运行时而不是编译时工作,因此当您实例化 Foo 时,编译器会看到 Foo

我可以想到以下三个选项:

(1) 转换实例:

let f = new Foo() as Foo & IValidatable;
let isValid = f.checkValidation();

(2) 将类投射到交叉点:

interface FooConstructor {
    new (): Foo & IValidatable;
}

let f = new (Foo as FooConstructor)();
let isValid = f.checkValidation();

(3) 使用工厂函数:

function fooFactory(): Foo & IValidatable {
    return new Foo() as Foo & IValidatable;
}

let f = fooFactory();
let isValid = f.checkValidation();

(code in playground)

【讨论】:

  • 感谢您的回复。如果通过“装饰器在运行时工作而不是编译时工作,那么当您实例化 Foo 时,编译器会看到 Foo。”您是在暗示这永远不会奏效,即使在原则上,我认为这是不正确的。这就是我包含“工作”示例的部分原因:T​​S 可以在类似情况下做出正确的推断。
  • 我并不是说“这永远行不通”,事情就是这样。如果编译器将 Foo 的定义替换为 validate(Foo) (这是您对工作示例所做的),则它可以工作。它也可以在运行时工作,因为 js 代码有这样的东西:Foo = __decorate([validated], Foo)(这也是同样的事情,只在运行时发生)
  • @DanielPratt 深入挖掘并找到一种使用接口为装饰器生成的方法输入类型的方法。这是 1 offs 的圣杯。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-19
  • 2020-11-02
  • 2016-11-26
  • 2015-07-23
相关资源
最近更新 更多