New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Idea: syntax for decorator composition. #515
Comments
It is very suggestive, but I have some comments:
const Mixer = (...decorators) =>
(element, descriptor) =>
decorators.reverse().reduce((element, decorator) => decorator(element, descriptor) || element, element);
let cool2 = Mixer(cool, logged); |
@falentio Yeah, my syntax idea was not very good. 😄 @pabloalmunia That Here's a Babel repl showing the same issue with Even with some adjustments to About syntax, what if it were const composed = @cool @logged('warning')
class MyClass {
@composed foo = 123
@composed bar = 123
} where In the future when/if function decorators come out, // this would not compose, but would decorate the function
const someFunc = @cool @logged('warning') function() {...}
// this would compose
const composed = @cool @logged('warning')
const otherFunc = @composed function() {...} Would it perhaps just be a decorator composition expression? Maybe when decorators are written out without decorating something, they just create a composed function. Example 1: // this would compose
const composed = (level) => @cool @logged(level)
const otherFunc = @composed('warning') function() {...} Example 2: function foo(decorator) {
return @decorator function() {...}
}
foo(@cool @logged('warning')) Example 3: console.log(typeof (@one @two @three)) // "function" |
Use CaseA library wants to import decorators, and compose them into new ones to export the new ones. For example, for a custom element library, it might do this: import {reactive} from 'some-reactive-library' // @reactive decorator makes a class field reactive
// _attribute decorator implementation
function _attribute() {
// ... map HTML attribute to JS field ...
}
/** A decorator that does two things: maps attributes to JS properties, and make properties reactive. */
export const attribute = @_attribute @reactive End user: import {createEffect} from 'some-reactive-library'
import {customElement, attribute} from 'some-custom-element-library'
@customElement('my-el')
class MyEl extends HTMLElement {
@attribute name = "Batman"
}
const el = new MyEl()
document.body.append(el)
createEffect(() => {
// This re-runs any time `name` changes because `@attribute` is composed with `@reactive`
console.log(el.name)
})
el.setAttribute('name', 'Superman') // triggers the effect, logs "Superman" to console |
Right now, composing decorators is much too cumbersome. You have to write conditional branches inside of a new function to handle all the
kind
s of decorators, and often you repeat logic, and can get it wrong.Rather than show how to compose decorators by using multiple
function
s inside a newfunction
, which I'm sure you're all familiar with, let me show the desired feature:Currently:
Idea (totally random syntax choice, but to show the idea):
This achieves the same thing as composing both
cool
andlogged
function
s together inside a newcool2
function, but in a much simpler way for the author of the composed decorator.The text was updated successfully, but these errors were encountered: