README
decorator-utils
Motivation
- — Decorator, what's that?
— It's just a proposal "aspect" syntax for JS. - — How does it work?
— Addy Osmany's answer - — Is there any ready solution?
— There're many awesome things around. Look at core-decorators and lodash-decorators. - — Do I need this lib?
— You should try this one before: decorator-utils by Luke Horvat - — ...
— Just give a chance to Google - — ...
— How about writing your own? Netanel Basal's practical tips may be very helpful. - — ...
— Yes, go ahead.
NOTE
There's no right way to support both decorator types: with @parentheses() and @plain. Holy War Thread: https://github.com/wycats/javascript-decorators/issues/23
Install
yarn add @qiwi/decorator-utils
Usage
Method
import {constructDecorator} from '@qiwi/decorator-utils'
const decorator = constructDecorator((targetType, target, param) => {
if (targetType === METHOD) {
return value => param || 'qux'
}
})
class Foo {
@decorator()
foo () { return 'bar' }
@decorator('BAZ')
baz () { return 'baz' }
}
Class
const decorator = constructDecorator((targetType, target) => {
if (targetType === CLASS) {
return class Bar extends target {
constructor (name, age) {
super(name)
this.age = age
}
}
}
})
@decorator()
class Foo {
constructor (name) {
this.name = name
}
foo () { return 'bar' }
}
Field & Param
import {createDecorator, FIELD, PARAM} from '@qiwi/decorator-utils'
const meta: any = {}
const decorator = constructDecorator(({
propName,
paramIndex,
targetType,
target,
args: [param]
}: IDecoratorHandlerContext) => {
if (targetType === PARAM) {
if (propName && typeof paramIndex === 'number') {
meta[propName] = meta[propName] || {}
meta[propName][paramIndex] = target
}
}
if (targetType === FIELD) {
if (propName) {
meta[propName] = param
}
}
})
class Foo {
@decorator('arg')
foo = 'bar'
bar(one: any, @decorator() two: any) {
return 'bar'
}
}
/**
Now `meta` is smth like:
{
foo: 'arg',
bar: {
1: Foo.prototype.bar,
},
}
*/
You may also apply the decorator to the class, but decorate its methods:
const decorator = constructDecorator((targetType, target) => {
if (targetType === METHOD) {
return () => {
return target().toUpperCase()
}
}
})
@decorator()
class Foo {
foo () { return 'bar' }
baz () { return 'baz' }
}
IDecoratorHandlerContext
constructDecorator
factory provides the handler access to the decorator context.
This data describes the specifics of the decorated target, decorator arguments and so on.
export type IDecoratorHandlerContext = {
targetType: ITargetType | null
target: ITarget
proto: IProto
ctor: Function
propName?: IPropName
paramIndex?: IParamIndex
descriptor?: IDescriptor
args: IDecoratorArgs
}