是否有类似Lombok的TypeScript? [英] Is there something like Lombok for TypeScript?

查看:68
本文介绍了是否有类似Lombok的TypeScript?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找减少NodeJS后端样板代码的方法.在龙目岛有例如通过注释为对象注入构造函数和getter/setter的可能性.

I'm looking for a way to reduce the boilerplate code of my NodeJS backend. In Lombok there is e.g. the possibility to inject constructors and getter/setter by annotation for objects.

有没有办法在TypeScript中做到这一点?

Is there a way to do this in TypeScript?

推荐答案

我快速搜索了它,发现了类似尝试将类似Lombok的功能引入TypeScript,但是正如您所看到的那样,这些项目很稀少,没有得到广泛使用.这意味着一个问题:为什么要这样的工具?

I googled it quickly and found projects like this which attempt to bring Lombok-like capabilities to TypeScript, but as you can see, those project are scarce and not that widely used. That implies a question: Why would you want a tool like that?

TS在减少样板方面已经非常不错.当我定义一个类时,通常是这样的:

TS is already pretty good in reducing boilerplate. When I define a class, I usually do it like this:

class A {
  constructor(private fieldA: string, private readonly fieldB = 0) {}
}

这很简洁,不是吗?我猜您正在将TS的功能与Java的功能进行比较.Java非常罗word,Lombok对此提供了很大帮助.但是 TS 和 JS 是不同的,虽然 Lombok 解决的一些问题已经被 TS 解决了,但其他问题在 TS 和 JS 的世界中都不是问题.

This is quite concise, isn't it? I guess you are comparing capabilities of TS to those of Java. Java is very wordy and Lombok helps with that greatly. But TS and JS are different, and while some problems, which Lombok solves, are solved by TS already, others are not an issue in the world of TS and JS.

首先,以上语法使用访问修饰符创建某些类型的类字段,并且您还可以在 fieldB 的前面发现 readonly 关键字及其默认值 0 .最重要的是,它们与构造函数一起创建,该构造函数在执行时隐式将值分配给实例字段(请参见,没有 this.fieldA = fieldA ).因此,这已经远远超过了龙目岛注入构造函数的能力.关于此的注意事项:在JS中(因此在TS中),只能有一个构造函数.JS不支持方法重载.

First of all, the syntax above creates class fields of certain types, with access modifiers and you can also spot the readonly keyword in front of fieldB and its default value 0. On top of that, those are created together with a constructor, which implicitly assigns values to instance fields upon execution (see, there is no this.fieldA = fieldA). So this already more than covers the Lombok's capability to inject constructors. Note on this: In JS (and therefore in TS), you can have only single constructor. JS doesn't support method overloading.

关于吸气剂/吸气剂,现在在JS(或TS)中使用的方式与在Java中不同.在JS中,通常直接使用字段是一种规范,而setter和getter仅在需要的特殊情况下使用:

Now about the getters/setters, those are not used the same way in JS (or TS) as they are in Java. In JS, it is a norm that you are working with fields directly, and the setters and getters are used only in special cases where you want to:

  1. 在运行时中仅通过定义getter来禁止将值设置为对象的属性.现在,这通常有点矫kill过正,并且由于您使用的是TS,因此您可以将字段声明为 readonly ,编译器会确保您未分配该字段属性-无需使用吸气剂.如果您使用JS开发时未进行编译时检查,则约定是使用下划线标记私有的属性(您绝对不应修改的属性).无论哪种方式,都可能会发生您不应该修改的变量被修改的情况,但是与Java不同,这不被认为是足以在JS(和TS)中的任何地方使用get/set的原因.相反,如果您确实需要确定运行时未进行任何修改,则可以使用前面提到的不带setter的getter,或者将对象的属性配置为不可写.
  2. 在设置/获取函数中具有自定义逻辑是采用它们的另一个很好的理由.常见的用例是从多个变量中计算出一个吸气剂,但您仍然希望它看起来像对象上的一个字段.这是因为在JS中,当您调用getter时,实际上并没有在getter名称后使用().现在,由于此逻辑是自定义的,因此不能仅通过使用注释来生成它.
  1. Forbid setting a value to an object's property in runtime by defining only a getter. Now this is usually a bit of an overkill, and since you use TS, you can just declare the field as readonly and compiler will make sure you don't assign to that property - no need to use a getter. If you develop in JS without compile time checks, the convention is to mark properties that are private (those you definitely shouldn't modify) with underscore. Either way, it can still happen that you modify a variable that you aren't supposed to modify, but unlike in Java, this is not deemed a reason good enough to use get/set everywhere in JS (and TS). Instead, if you really need to be certain that no modifications happen in runtime, you either use the aforementioned getter without setter, or you configure the object's property as non-writable.
  2. Having a custom logic in set/get functions is the other good reason to employ them. A common use case for this is a getter that is computed out of multiple variables but you still want it to look like an field on an object. That's because in JS, when you invoke a getter, you don't actually use () after the getter name. Now because this logic is custom, it can't be generated just by using an annotation.

如您所见,Lombok在Java中处理的一些问题已在TS中解决,而其他问题则不是问题.

So as you can see, some problems Lombok deals with in Java are already dealt with in TS and others are non-issues.

编辑5-9-2021-回答@Reijo的问题: Lomboks的功能超越了getters/setters/constructors.看着@Builder注释,我对您对此有何看法感兴趣.

如果问题仅在于是否有一个TypeScript/JavaScript库提供的功能集合与Lombok for Java差不多,那么据我所知,答案是否定的.我认为部分原因是TypeScript提供了开箱即用的功能(正如我上面已经概述的那样),这使我回到了Java比诸如TypeScript或Groovy之类的语言更需要Lombok的地步.当您需要TS未提供的内容(例如构建器模式)时,可以使用库来解决特定问题,例如

If the question is just about whether there is a TypeScript/JavaScript library that offers more or less the same collection of utilities as Lombok for Java, to my knowledge the answer is NO. I think partly it is due to capabilities that TypeScript provides out of the box (as I already outlined above), which brings me back to the point that Java needs Lombok more than languages like TypeScript or Groovy do. When you need something that TS doesn't provide, like the builder pattern, you can use libraries solving a particular problem, like builder-pattern (using JS Proxy in its core) or thanks to the flexible nature of JS (and in effect TS) write it on your own easily.

很好,但是您可能想以更具声明性的方式添加功能-通过注释(在TS世界中,这些称为

That's all nice, but you'd perhaps like to add functionality in more declarative way - via annotations (in TS world those are called decorators and they work differently), as Lombok does it. This might prove complex.

首先,如果通过TS中的装饰器修改类型,TS编译器将无法识别更改.因此,如果您通过在装饰器中向其添加方法来扩充类,则TS将无法识别该新方法.有关详细信息,请参见此讨论.

First of all, if you modify the type via decorator in TS, TS compiler doesn't recognize the change. So if you augment class by, let's say, adding a method to it in your decorator, TS won't recognize that new method. See this discussion for details.

这意味着你要么放弃装饰器,而是使用函数来修改类型(你可以),要么你深入研究 AST.这就是龙目岛的工作方式.它在称为注释处理的编译阶段中采用带注释的类型,这要归功于javac(和Eclipse编译器)的入侵,修改了它们的AST(例如,为给定的类创建内部生成器).可以使用TS/JS以某种类似的方式来做到这一点.

This means that you either give up on decorators and use functions instead to modify the type (which you can), or you dive into AST. That's btw how Lombok works. It takes annotated types in a compilation phase called annotation processing and thanks to a hack in javac (and Eclipse compiler) modifies their AST (to eg. create an inner builder for given class). One could do it in a somewhat similar way with TS/JS.

尽管在TS或JS中没有像注释处理那样的东西,但是您仍然可以创建一个构建步骤,该步骤采用源代码并修改它的AST以实现您的目标(Babel的工作方式也是如此).这可能导致将方法添加到类,基于使用的注释(广义上,不一定是装饰器)生成生成器等.

Though there is nothing like annotations processing in TS nor JS as such, you could still create a build step that takes a source code and modifies it's AST to achieve your goals (which is how Babel works too). This might result in adding a method to a class, generating a builder etc. based on an annotation (in a broad sense - not necessarily a decorator) used.

这种方法是一个挑战.除了AST是一个高级主题之外,即使您可以使用它,您也需要IDE的支持,如今,这也意味着来自语言服务器的支持.那不是为了胆小的人.

This approach is a challenge though. Besides AST being an advanced topic, even if you get it working, you'd need support from your IDE, which nowadays also means support from language servers. And that's not for the faint of heart.

但是,如果您打算为TS创建Lombok之类的东西,我的编辑不应吓supposed任何人,因为似乎有些人希望在TS/JS世界中看到它.它应该只向您显示未来的情况;).

However, my edit is not supposed to scare anyone away if you plan to create something like Lombok for TS, since it seems quite some people would like to see it in TS/JS world. It should only show you what lies ahead ;).

这篇关于是否有类似Lombok的TypeScript?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆