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 中查看悬停时的完整类型定义?
使用Typescript和类组件装饰器时如何在Vue Router中传递props