tc39 / proposal-decorators-previous

Decorators for ECMAScript
183 stars 16 forks source link

Decorator call signatures are ambiguous #24

Open dongryphon opened 7 years ago

dongryphon commented 7 years ago

Consider:

@foo
class A {
}

@foo(A)
class B {
}

I am attempting to provide a decorator that accepts fully optional arguments including optional class parameters. Is there some idea brewing how to reliably determine the context of such things?

Given the current spec as I understand it (using babel-plugin-transform-decorators-legacy), there is no way to distinguish the above forms. To support case 1 you would do:

  function foo (C) {
      // decorate class C
  }

To support case 2, you would do:

  function foo (p) {
      return C => {
          // decorate C using p
      };
  }

But since the parameter is a class there is no way to tell which form is being invoked.

If I could wish :) I would rather write decorators like so:

  function foo (args, C) {
      // decorate C using optional additional args
  }

The idea there is that args is whatever (if anything) is supplied in parens after the decorator name. So to handle both cases:

  function foo (args, C) {
      if (args && args.length) {
          // args is an array if @foo() of some form was used
         let p = args[0];
      } else {
          // @foo w/no args was used...
      }
  }

One could debate whether args should be an empty array to distinguish @foo from @foo() I suppose.

dongryphon commented 6 years ago

Even though the syntax is borrowed from function calls (as it does in most annotation language features) it is not fair to say it is a function call when clearly there must be much more to the consumption of whatever follows the @