Typescript:使用装饰器时的类型推断

Posted

技术标签:

【中文标题】Typescript:使用装饰器时的类型推断【英文标题】:Typescript: Type inference when using decorator 【发布时间】: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 中,它将减少最终用户的拼写错误。 哦,我明白了。谢谢!我很好奇。 【参考方案1】:

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

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

【讨论】:

【参考方案2】:

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

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

interface IDecorate 
  extendedtMethod(): number;

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

@decorate
@anotherDecorator
class MyClass 
  // ...


interface MyClass extends IDecorate, IAnotherDecorator 

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

【讨论】:

以上是关于Typescript:使用装饰器时的类型推断的主要内容,如果未能解决你的问题,请参考以下文章

如何在 VSCode、TypeScript 中查看悬停时的完整类型定义?

使用refs实现迭代器时的生命周期推断问题

使用Typescript和类组件装饰器时如何在Vue Router中传递props

使用Typescript和类组件装饰器时如何将数组传递给Vue中的props

TypeScript:使用可变元组类型进行依赖类型推断

TypeScript:推断嵌套联合类型的类型