Decorators for functions

Ron Buckton Ron.Buckton at microsoft.com
Tue Oct 20 19:26:14 UTC 2015


I can think of numerous examples of how decorators could apply to functions, and I’ve added them to a gist<https://gist.github.com/rbuckton/37e944f7986e6833949e> [1] for easier consumption. It’s true that simple decorators for functions can work as simply as function calls, but this becomes a bit unwieldy if you need to compose multiple decorators on a single function.

Consider a scenario combining decorators providing runtime type information as an annotation with one that adds runtime type checking. With decorators this might be:

```js
@paramtypes(() => [Number, Number])
@returntype(() => Number)
@checked
function add(x, y) { return x + y }
```

If I just use function expressions, this is feasible if a bit awkward:

```js
const add =
    paramtypes(() => [Number, Number])(
        returntype(() => Number)(
            checked(
                function (x, y) { return x + y; })))
```

It feels a bit developer-hostile to have to rebalance parentheses if you want to add a decorator, and there are ASI hazards if you misplace an opening paren. Also, you can no longer infer the function name “add” from the const binding.

Using `::` isn’t a great replacement either, as there are many hazards such as:

```js
// The following means “call `decorator` with `this` bound to the function object”.
// Also, it becomes impossible to infer the function name “a” from the let binding.
let a = function() { }::decorator(x)

let b = function() { }
::some.decorator(x) // ASI hazard as `::` can be either prefix or infix.
```

One of the initial drivers for decorators was class methods, as there’s no expression context immediately inside the class body in which you can use either of the above scenarios. This necessitated a declarative form for decorators to allow these scenarios to exist. Having parity across class methods, classes, and functions (of all kinds) presents a more consistent story to developers. The upswing in decorator use in both TypeScript and Babel has been very positive, with libraries like Angular leveraging decorators heavily in their codebase. Since we introduced decorators into TypeScript, we’ve had a fair bit of feedback requesting support for function decorators.

I do think function decorators should wait until the Class/Property decorators proposal advances further along the standards track. Axel’s initial concerns/questions around hoisting are valid and there isn’t a clear consensus on the semantics for functions. That said, I’ve been mostly in the camp of introducing TDZ for function declarations that have decorators. Decorators are a new syntactic form and we have the opportunity to communicate this caveat with the development community by the time the feature lands. It seems easy enough to explain that:

```js
@decorator
function func() { }
```

Is the equivalent of:

```js
let func = @decorator function() { }
```

Introducing TDZ allows to generally warn early as part of the static semantics, so developers won’t fall into a well with respect to adding a decorator to a function and not being able to quickly understand how that change affects the behavior of their code.

I’m not certain what the current plan of record is, but the best approach may be:


1.       Advance and get consensus on the Class/Property decorators proposal

2.       Draft a separate proposal for decorators on function expressions, generator function expressions, and arrows

3.       Draft a separate proposal for decorators on function declarations

Steps 1 and 2 above shouldn’t be significantly difficult and don’t necessarily introduce any major new semantics outside of the decorators themselves. Step 3 covers a thornier issue as it not only introduces the new semantics of decorators but also introduces side-effects due to hoisting.

Ron

[1] https://gist.github.com/rbuckton/37e944f7986e6833949e


From: es-discuss [mailto:es-discuss-bounces at mozilla.org] On Behalf Of Andrea Giammarchi
Sent: Tuesday, October 20, 2015 3:34 AM
To: Axel Rauschmayer <rauschma at icloud.com>
Cc: es-discuss mailing list <es-discuss at mozilla.org>
Subject: Re: Decorators for functions

You haven't provided a single use-case example, like how are you going to decorate a function or why.

IMO if implemented it will be incompatible with non ES6 code unable to distinguish between classes and functions unless fully transpiled, making decorators less portable.

One thing I like about current state is that you can use decorators even in ES5 browsers [1]

Just my 2 cents, Regards


[1] as shown in the second example of the universal mixin module https://github.com/WebReflection/universal-mixin#universal-mixin-<https://na01.safelinks.protection.outlook.com/?url=https%3a%2f%2fgithub.com%2fWebReflection%2funiversal-mixin%23universal-mixin-&data=01%7c01%7cron.buckton%40microsoft.com%7c50c27148ba3543c448f608d2d939f7c4%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=T1q%2bKVVIyc%2bNxSyG9Ri%2bmNAMPqq3p6Ydofoe1WQrg5U%3d>

On Tue, Oct 20, 2015 at 10:30 AM, Axel Rauschmayer <rauschma at icloud.com<mailto:rauschma at icloud.com>> wrote:
https://github.com/wycats/javascript-decorators/blob/master/README.md<https://na01.safelinks.protection.outlook.com/?url=https%3a%2f%2fgithub.com%2fwycats%2fjavascript-decorators%2fblob%2fmaster%2fREADME.md&data=01%7c01%7cron.buckton%40microsoft.com%7c50c27148ba3543c448f608d2d939f7c4%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=2fTFCt8Rrkx6pTvFLkcl8xfV5EKny35QpLPVTmm0aV8%3d>

The decorator proposal does not include decorators for functions, because it isn’t clear how to make them work in the face of hoisting.

However, it would be great to have them. I see two possible solutions:

– A decorator on a function declaration prevents hoisting.

– Enable decorators for function expressions, arrow functions and generator function expressions.

Does either one of those make sense?

Axel

--
Dr. Axel Rauschmayer
axel at rauschma.de<mailto:axel at rauschma.de>
rauschma.de<https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2frauschma.de&data=01%7c01%7cron.buckton%40microsoft.com%7c50c27148ba3543c448f608d2d939f7c4%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=Vclw%2fyI29j4WqkHWjTgaZtoL12pnJNCWYBJK4wTYVA0%3d>



_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org<mailto:es-discuss at mozilla.org>
https://mail.mozilla.org/listinfo/es-discuss<https://na01.safelinks.protection.outlook.com/?url=https%3a%2f%2fmail.mozilla.org%2flistinfo%2fes-discuss&data=01%7c01%7cron.buckton%40microsoft.com%7c50c27148ba3543c448f608d2d939f7c4%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=7t2BTGHrR322y2keuKyyEhgwUSIOCCN3vzv9CbXzdn8%3d>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20151020/812db320/attachment-0001.html>


More information about the es-discuss mailing list