lodash-decorators
Method Decorators for lodash functions.
Install
npm install --save lodash-decorators
Usage
For more in depth documentation please visit Lodash
Decorators are exported as both start case and lower case.
import { Debounce } from 'lodash-decorators';
is the same as
import { debounce } from 'lodash-decorators';
They can also be imported directly.
import Debounce from 'lodash-decorators/debounce';
With Arguments
Many of the lodash decorators can contain arguments.
Debounce
DebounceAll
Throttle
ThrottleAll
Memoize
MemoizeAll
After
AfterAll
Before
BeforeAll
Ary
Curry
CurryAll
CurryRight
CurryRightAll
Rest
Partial
PartialRight
Wrap
Flow
FlowRight
Delay
Defer
Bind
BindAll
OverArgs
Rearg
Mixin
Attempt
Example
import { After, Debounce, Memoize, Curry } from 'lodash-decorators'
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
@After(3)
@Debounce(100)
getFullName() {
return `${this.firstName} ${this.lastName}`
}
@Curry(2)
@Memoize()
doSomeHeavyProcessing(arg1, arg2) {
}
}
Without Arguments
Some decorators don't take any arguments at all.
Example
import { Once } from 'lodash-decorators'
class person {
constructor(firstname, lastname) {
this.firstname = firstname;
this.lastname = lastname;
}
@Once
getfullname() {
return `${this.firstname} ${this.lastname}`
}
@Tap
popIt(list) {
list.pop();
}
}
const person = new Person();
person.popIt([1, 2, 3]);
Partials
Some decorators work slightly differently than you would expect
them to work than lodash.
These can take a Function
as their first argument or a String
.
If the argument is a String
then a Function
is resolved from
the current object.
Example
import { Partial } from 'lodash-decorators'
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
getName(type) {
return type === 'firstName' ? this.firstName : this.lastName
}
@Partial('getName', 'firstName')
getFirstName() {}
@Partial('getName', null)
getLastName() {}
@Wrap('getName')
getUpperCaseName(fn) {
return fn().toUpperCase();
}
}
const person = new Person('Joe', 'Smith');
person.getFirstName();
person.getLastName();
person.getUpperCaseName();
Composition
You can use methods like compose
and flow
similiar to
partials. The arguments are resolved the same way partials
are resolved.
Example
import { Flow } from 'lodash-decorators'
import { kebabCase } from 'lodash';
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
getName() {
return `${this.firstName} ${this.lastName}`;
}
@Flow('getName', kebabCase)
logName(name) {
console.log(name);
}
}
const person = new Person('Joe', 'Smith');
person.logName();
Instance Decorators
Normally decorators are applied to the prototype method
of the class you are working with, but with some of these
decorators that is not the desired behavour. These
decorators are applied at the instance level.
Debounce
Throttle
Memoize
After
Before
Curry
CurryRight
Mixin
You can mixin methods into a class by using the Mixin
decorator.
Example
import { Mixin } from 'lodash-decorators';
const MyOtherApi = {
someCoolMethod() {
}
};
@Mixin(MyOtherApi)
class Person {}
Person.prototype.someCoolMethod === MyOtherApi.someCoolMethod;
Attempt
You can wrap a method in a lodash attempt method.
Example
import { Attempt } from 'lodash-decorators';
class Person {
@Attempt()
throwAnError() {
throw new Error();
}
@Attempt()
doNotThrowAnError() {
return '0_o';
}
}
const person = new Person();
let result = person.throwAnError();
result instanceof Error;
result = person.doNotThrowAnError();
result === '0_o';
Bind
Bind takes arguments based on lodash's bind and binds the Function
to
the current instance object.
Example
import { Bind } from 'lodash-decorators'
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
@Bind()
getName() {
return `${this.firstName} ${this.lastName}`;
}
@Bind('Joe')
getUpperCaseName(name) {
return name.toUpperCase();
}
}
const person = new Person('Joe', 'Smith');
person.getName.call(null);
person.getUpperCaseName();
You can also bind entire classes with bindAll
or bind
.
Example
import { BindAll } from 'lodash-decorators'
@BindAll()
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
getName() {
return `${this.firstName} ${this.lastName}`;
}
}
const person = new Person('Joe', 'Smith');
person.getName.call(null);
v4 Breaking Changes
Version 4 is a rewrite of the library and has many breaking changes.
Only certain decorators make sense to be applied to getters/setters. Before you could specify the target of the decorator like debounce.set(15)
. This behavior is
removed and decorators that make sense to apply to getters/setters are configured to be applied to methods and either the getter or the setter. For example:
class MyClass {
@Debounce(1000)
get value() {
return this._value;
}
set value(val) {
this._value = val;
}
@Debounce(15)
fn() {}
}
This keeps the API cleaner and doesn't require the developer to know how the decorator applies to the descriptor.
No longer force instance decorator onto prototype
There is no longer a Proto
decorator attached to instance decorators. Most instance decorators now have a counterpart that applies to the prototype instead of the instance. Debounce.Proto()
is now DebounceAll()
.
Curry is now an instance decorator
The curry decorator is now an instance decorator in order to keep the calling context consistent. The original function before being curried is bound to the instance. You can apply curry to the prototype by using CurryAll()
.
Removal of extensions and validation package
All extensions like enumerable
have been removed in favor of core-decorators. There may be some slight over lap like debounce
and throttle
. Fair warning, instance decorators may not play nice with other implementations of instance decorators.
We want to keep lodash decorators focused specifically on lodash specific functions.
Other breaking changes
Attempt
now takes an argument to line up with lodash API.Bind
used on a class no longer delegates to BindAll
. Use BindAll
instead.
v4 Improvements
- Instance and prototype decorators can be in any order.
- Ships with TypeScript typings.
- Predictable performance.
- Improvements to Bind decorator.
- Improved API for decorator factory.
- More and better unit tests.
- Better performance with instance decorators.
- Single imports with
import { Debounce } from 'lodash-decorators/debounce'
;
Author: Steven Sojka
MIT Licensed