【问题标题】:Typescript: Type inference when using decoratorTypescript:使用装饰器时的类型推断
【发布时间】:2016-07-23 05:11:50
【问题描述】:

我想知道为什么当我在一个类的 Typescript 中使用装饰器或注释时。编译器无法推断类的新类型。如果我不使用装饰器并在 ES5 中使用旧方法(即手动调用装饰器),它显然可以工作。

例如,这里有一个显示问题的示例:

function decorate(Target: typeof Base): IExtendedBaseConstructor {
  return class extends Target implements IExtendedBase {
    public extendedtMethod(): number {
      return 3;
    }
  };
}

interface IBase {
  baseMethod(): number;
}

interface IExtendedBase extends Base {
  extendedtMethod(): number;
}

interface IExtendedBaseConstructor {
  new(): IExtendedBase;
}

@decorate
class Base implements IBase {
  public baseMethod(): number {
    return 5;
  }
}

const test = new Base();
test.baseMethod(); // OK
test.extendedtMethod(); // NOT OK, typescript think, Base is still Base but we decorated it.

使用旧方法,它可以工作:

class Base implements IBase {
  public baseMethod(): number {
    return 5;
  }
}

const ExtendedBase = decorate(Base);

const test = new ExtendedBase();
test.baseMethod(); // OK
test.extendedtMethod(); // OK

提前致谢。

【问题讨论】:

  • 这种模式有什么好处? this code 不是更容易理解吗?
  • 你是对的。在这种情况下,这种模式是没有用的。但新的前端框架(如 angular2)选择使用装饰器而不是继承来声明新组件。
  • 我编写了一个库,它向用户建议一个帮助器来创建类 API(其中注入了一些参数和有用的方法)。因此,我创建了一个提供功能的抽象 Api 类和一个通过meta-data 将 api 注册到我的框架中的装饰器。在这种情况下,我的用户必须这样做:import { AbstractAPI, Api } from 'myLib' @Api(...) class UserApi extends AbstractAPI {} 我的 SO 问题也与此有关。如果我可以删除扩展并将所有内容合并到我的装饰器@Api 中,它将减少最终用户的拼写错误。
  • 哦,我明白了。谢谢!我很好奇。

标签: javascript oop typescript decorator


【解决方案1】:

现在这不起作用。 github上有一个pending issue,可以让类装饰器改变类的类型。

我建议在实施之前采用您提到的“旧方式”。

【讨论】:

    【解决方案2】:

    有一种方法可以使这项工作只需要一点额外的编码。

    对于任何类装饰器,使用其属性和方法创建一个接口。以某种方式命名它,以便您可以轻松地将其与它所描述的装饰器相关联。在你的情况下,它可能是:

    interface IDecorate {
      extendedtMethod(): number;
    }
    

    对于任何需要此装饰器的类,您只需创建一个与该类同名的接口,并让它扩展所有必要的装饰器接口:

    @decorate
    @anotherDecorator
    class MyClass {
      // ...
    }
    
    interface MyClass extends IDecorate, IAnotherDecorator {}
    

    现在,只需关闭 ESLint 或 TSLint 对空接口的警告,您就可以开始了。装饰器添加的任何方法或属性现在都可以在装饰类本身中使用。

    【讨论】:

      猜你喜欢
      • 2018-08-02
      • 2018-06-01
      • 2021-11-24
      • 1970-01-01
      • 2022-08-15
      • 2019-07-23
      • 2020-01-17
      • 1970-01-01
      • 2019-07-20
      相关资源
      最近更新 更多