Undecorate Your Decorators

Jeremy Gayed
4 min readDec 2, 2016

--

I’m a big fan of the @decorator syntax, a TC39 proposal currently in stage-2. So I wrote an Undecorate Codemod that “undecorates” the syntax to plain “curried” function style. And I hope nobody ever uses it. Read on to learn why.

What’s so special about Decorators?

But first, why am I such a big fan of decorators? Not only do they allow for a very elegant and expressive syntax, but I find that just having this syntax available enables developers to reach for functional composability rather than repeating logic, cluttered ‘utility’ modules, or terse curried functional style code that’s difficult to read.

To be fair, there are other, very solid alternatives available today. One such popular alternative is the recompose library, but I still find the @decorator syntax much easier to reason about and read.

What it looks like

One of the core use cases I find decorators helpful in is for building out Higher Order React Components (HoC). I find that being able to compose multiple HoC together in the succinct and expressive way that decorators allow to be quite elegant. (Let’s leave the argument of HoC vs Function as Child Component pattern for another day).

Here’s an example of a Relay-backed component that also utilizes a styling HoC library. You can imagine the list of HoC growing as individual, yet separate pieces of logic can be abstracted out into wrapping components (such as for tracking metrics, etc.).

Yeesh! And you can imagine how increasingly difficult this becomes to read after only adding one or two more HoCs.

And now with decorators

Here’s that same component, but written using decorators.

Ah — it’s like a breath of fresh air! You could also have taken it a step further and inlined style and query values within the decorator calls, or even defined those values in separate files — whichever you feel is the neatest!

For those keeping score, Relay does not ship with a decorator-compatible syntax. But that’s very simple to provide yourself, here’s withRelay.js:

But wait, there’s more!

The decorator proposal also includes the ability to decorate individual class properties, not just the entire class, as we’ve seen in the above examples.

Here’s an example use case for a class property decorator. In this case we invoke an internal tracking library to track a particular user action:

One thing to note, however, is that my Undecorate Codemod does not currently support undecorating class properties, only the top-level class declaration itself. But that hopefully shouldn’t stop you from using it on class properties!

How to enable decorators in your app today

Unfortunately, because of some issues with how Babel used to transform decorators and/or with how the spec is currently written, decorator transformation is disabled in Babel v6.

In the meantime, you can use babel-plugin-transform-decorators-legacy, which is still quite easy to include!

Note that if you’re currently also using babel-plugin-transform-class-properties the order of these plugins matter, see here for more info. This is part of the reason it was disabled in Babel v6, since typically plugin order should not matter.

You can include it like so in .babelrc

"plugins": [
"transform-decorators-legacy",
"transform-class-properties"
]

Now, about the Undecorate Codemod

So then, why create the Undecorate Codemod? Courage.

No, but really, it’s more of a “safety net” in case the decorator syntax doesn’t make it through to an official ESNext release (there’s no way to know which ES version it will make it in, if any). But in the interest of writing tomorrow’s JavaScript today, I felt a codemod that could act as an escape hatch would help us feel a little more comfortable taking this step now.

This is also why I hope nobody ever uses this codemod. I’d much rather see the proposal graduate through to an ESNext release and I can kill the codemod! 😃

ESNext is a bit of a loaded term. I’ve seen some folks use the term ESFuture, ES20xx, etc. The point is, this is still a proposal and may or may not ever even make it into an ECMAScript release.

Some things to note about the Undecorate Codemod

  • It only supports decorators on Class declarations
  • It does not (yet?) support Class property decorators
  • It doesn’t desugar exactly to the spec. I wanted the output to be somewhat more readable, perhaps something that you would write by hand if you didn’t have decorator syntax support and weren’t using a currying library.
  • I hope nobody ever needs to use it — I’m rooting for you Yehuda Katz and Brian Terison!
  • Contributions welcome, of course! I’d love to add decorated Class property support for example.

Usage

Simply follow the Setup & Run instructions in the repo: https://github.com/tizmagik/undecorate-codemod/blob/master/README.md#setup--run

My hope is that this codemod does “just enough” to help convince teams to start experimenting with the decorator syntax. If you found this useful, or have any thoughts, comments or suggestions please leave a response here or message me @tizmagik. Happy decorating!

--

--

Coptic Orthodox Christian. Lead Software Engineer @nytimes. Lover of all things JavaScript 🤓