npm package: @slietar/decorators
Description: An advanced library of ES16 decorators
Latest version: 0.2.0-beta.4

# Decorators

Highly experimental.

## Install

```sh
$ npm install @slietar/decorators
$ tsd link # if using TypeScript
```

## Decorators appliance

| Name               | Class | Method | Parameter | Property | Status |
|--------------------|:-----:|:------:|:---------:|:--------:|:------:|
| `@abstract`        | ✓     | ✓ (?)  | ✗         | ✓ (?)    | ❋      |
| `@animationFrame`  | ✗     | ✓      | ✗         | ✗        | ◉      |
| `@autobind`        | ✓<br>*alias: `factorize()`* | ✓      | ✗         | ✗        | ◎      |
| `@check`           | ✓ (?) | ✓      | ✗         | ✓ (?)<br>*only: `set()`* | ❋      |
| `@curry`           | ✗     | ✓      | ✗         | ✗        | ◎      |
| `@defaults`        | ✗     | ✗      | ✓         | ✗        | ✪      |
| `@defaults` *(extended implementation)* | ✗     | ✗      | ✓         | ✓<br>*only: `set()`* | ❋      |
| `@deprecate`       | ✓     | ✓      | ✓         | ✓        | ✪      |
| `@desync` or `@async` | ✗     | ✓      | ✗         | ✓        | ◎      |
| `@experiment`      | ✓     | ✓      | ✓         | ✓        | ◉      |
| `@memoize`         | ✗     | ✓      | ✗         | ✗        | ❋      |
| `@nonconfigurable` | ✗     | ✓      | ✗         | ✓        | ◎      |
| `@nonenumerable`   | ✗     | ✓      | ✗         | ✓        | ◎      |
| `@once`            | ✓     | ✓      | ✗         | ✗        | ◉      |
| `@once` *(extended implementation)* | ✓     | ✓      | ✗         | ✓        | ❋      |
| `@readonly` or `@nonwritable`         | ✗     | ✓      | ✗         | ✓        | ◎      |
| `@serialize`       | ✓     | ✗ (?)  | ✗         | ✗ (?)    | ❋      |
| `@stage`           | ✓     | ✓      | ✓         | ✓        | ❋      |

<small><em>
❖ ...,
❋ not confirmed,
◎ not implemented,
◉ implemented,
✪ tested (coverage 100%) and fully typed
</em></small>

Maybe:
* `@promise`: `Q(r) if !isPromise(r)` (Method, Property (?))


## Usage

### `@deprecate()`

```js
@deprecate()
class A {
  @deprecate()
  p;

  @deprecate('Custom message')
  m() { }

  n(a, @deprecate(void 0, customLogger) b) { }
}

let a = new A() // on console.warn - DEPRECATION A: This feature is deprecated and will be removed in future versions
a.m(); // DEPRECATION A#m(): Custom message

a.n('1'); // nothing
a.n('1', '2') // on customLogger.warn - DEPRECATION A#n(1): ...

a.p; // DEPRECATION A#p: ...
a.p = 3; // nothing
```


### Notes on `@desync`

On method:

```js
class A {
  @desync(done => setTimeout(done, 500)) // same as @debounce(500)
  b() {

  }
}
```

On parameter:

```js
class Auth {
  save(@desync() user) {
    this.user = user;
  }
}

var a = new Auth();

a.save(getPromise());
```

### Notes on `@serialize`

```js
@serialize()
class A {
  constructor() {
    this.a = 42;
  }

  getA() {
    return this.a;
  }
}

let json = JSON.stringify(new A());
// => { constructor: 'A', properties: { a: 42 } }

let parsed = JSON.parse(json);
let obj = A.fromJSON(parsed);
// => { a: 42, getA: [Function: getA] } }
```

```js
@serialize()
class A {
  @serialize()
  a = 'John Doe';

  @nonserializable()
  b = 42;

  //        (     stringify     ) (       parse       )
  @serialize(c => c.toUpperCase(), c => c.toLowerCase())
  c = 'lorem ipsum';
}

new A()
  .__serializeProperties = {
    a: true,
    b: false,
    c: { serialize: [Fn], deserialize: [Fn] }
  };
```


## TypeScript definitions

```ts
declare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;
declare type PropertyDecorator = (target: Object, propertyKey: string | symbol) => void;
declare type MethodDecorator = <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;
declare type ParameterDecorator = (target: Function, propertyKey: string | symbol, parameterIndex: number) => void;
```