【问题标题】:TypeScript class decorator to create method with same typed arguments as constructorTypeScript 类装饰器创建具有与构造函数相同类型参数的方法
【发布时间】:2017-10-21 07:05:53
【问题描述】:

在 ES6 类中,我发现自己创建静态 create 方法,更喜欢使用 ClassName.create() 而不是 new ClassName()new ClassName,因为我遇到了一些与访问新的属性有关的愚蠢错误创建的对象;滑倒并做new ClassName.methodCall()而不是(new ClassName).methodCall()。 IMO 更干净,ClassName.create().methodCall() 更不容易出现愚蠢和难以捕捉的错误。

但是,在每个类上都这样做会变得乏味和冗长,所以我想知道是否有一种方法可以使用 TS/ES6 装饰器以便我可以这样做

@Creatable // or @Creatable()
class ClassName {
    constructor(arguments: IArguments) {}
}

这将在类上创建一个static create(arguments: IArguments) { return new this(arguments); } 方法,具有相同的参数,包括类型。

这可能吗?如果可以,怎么做?

【问题讨论】:

  • 扩展可创建;类可创建 { create(args...){ var obj=Object.create(this); this.constructor.call(this,...args);return obj;}}
  • 忘了说我想让它输入安全,将编辑问题
  • 其实new ClassName(…).methodCall() 工作得很好。只有当您省略构造函数参数列表 (new ClassName.methodCall()) 时,您才需要将其分组到 (new ClassName).methodCall()
  • @Jonasw 不要为此使用继承(你的方法也不能满足 OP 的要求)
  • 看来你是对的,我有问题没有争论。我会更新问题,因为无论如何我都想使用.create() 模式

标签: javascript typescript ecmascript-6 decorator


【解决方案1】:

目前无法在 TypeScript 中使用装饰器轻松地将新方法添加到类中,为此可以使用 open issue

这样做需要使用类型断言,例如:

interface ICreatable<T> extends Function {
  new (): T;
  create: (...args) => T;
}

function Creatable() {
  return function (target) {
    target.create = (...args) => new target(...args);
    return target;
  }
}

@Creatable()
class Foo {...}

(<ICreatable<Foo>>Foo).create(...)

考虑到问题陈述,这是 XY 问题。虽然省略的构造函数括号是真正的问题。

实例化带和不带参数的类的简单方法是

new Foo().bar();
new Foo(1).bar();

不是

(new Foo).bar();

可选的构造函数括号通常被认为是不礼貌的,并且在样式指南中被禁止。如果一个习惯导致问题,它可以被认为是坏习惯,应该避免。只是不要那样做。这里不需要create 工厂方法。

【讨论】:

  • 将听取您的建议,仅在类名后使用括号。不过我会澄清这个问题,因为我仍然感兴趣;是@Creatable 还是@Creatable() 对我来说并不重要
  • 答案的第一部分解决了这个问题。如您所见,在 TS 中使用装饰器来做到这一点是不切实际的。
猜你喜欢
  • 2017-09-14
  • 2010-09-07
  • 2019-03-19
  • 1970-01-01
  • 2014-04-18
  • 1970-01-01
  • 1970-01-01
  • 2020-07-18
  • 1970-01-01
相关资源
最近更新 更多