npm package: @slietar/decorate
Description: An advanced __decorate helper for the TypeScript compiler
Latest version: 0.1.2

# Decorate

```js
class A() {
  constructor(@defaults({ name: 'foo', age: 45 }) options) {
    this.name = options.name;
    this.age = options.age;
  }
}

var a = new A({ name: 'bar' });

console.log(a.name, a.age) // outputs 'a' 45
```

## Compatibility

| Environment           | Class | Class constructor parameter | Class accessor | Function | Method | Method parameter | Object accessor | Property |
|-----------------------|:-----:|:---------------------------:|:--------------:|:--------:|:------:|:----------------:|:---------------:|:--------:|
| TypeScript            | ✓     | ✓                           | ✓              | ✗        | ✓      | *no descriptor*  | ✓      | *no descriptor*   |
| TypeScript + decorate | ✓     | `>= 0.1.1`                  | ✓ | *manually, in future versions* | ✓ | ✓            | ✓  ❋            | ✓        |
| Babel                 | ✓     | ✓                           | ✓              |✗         | ✓      | ✗                | ✓               | ✓ ❋      |
| ES16 proposal         | ✓     | ✓                           | ✓              | ✗        | ✓      | ✗                | ✓               | ✗        |

> ❋ not tested or not confirmed

#### Notes

* *no descriptor* means you cannot change the value of the parameter or property
* Babel needs option `--optional es7.decorators` or `--stage 1`
* For property decoration using Babel, also add `--optional es7.classProperties` or `--stage 0`

## How to use it

Run:
```sh
$ npm install @slietar/decorate --save-dev
```

### By overriding `__decorate` and `__param`

In a JS file:
```js
var d = require('@slietar/decorate');

global.__decorate = d.__decorate;
global.__param = d.__param;

require('./lib'); // require the main compiled TypeScript file compiled without __decorate & __param
```

TypeScript transpilation:
```sh
$ tsc --experimentalDecorators --noEmitHelpers --target ES5 # or ES6
```

### By overriding `Reflect.decorate` (no support for `__param`)

```js
// ES5
global.Reflect = require('@slietar/decorate').Reflect;

// ES6+
import { Reflect as _Reflect } from '@slietar/decorate';

global.Reflect.decorate = _Reflect.decorate;
```

### By manually decorating your targets (in future versions)

```js
import { deprecate } from '@slietar/decorators';
import 'decorate' from '@slietar/decorate';


function A() {

};

A.prototype.b = function () { ... };

decorate(A.prototype, 'b', deprecate());

A = decorate(deprecate(), 'class', A);

decorate(deprecate(), 'method', A, 'm');
```


## Decorator kinds

### Parameter decorator

```js
function decorator(target, key, descriptor, paramIndex) {
  let oldValue = descriptor.value;

  descriptor.value = (...args) => {
    var arg = args[paramIndex];

    /* for example */
    arg = arg.toUpperCase();

    return oldValue.call(this, ...args);
  };

  return descriptor;
}

function paramDecorator(...) {
  // => this.[target, key, signature]
  this.override((arg, self) => {
    // ...
  });
}

function classDecorator(...) {
  this.override((self) => {
    // ...
  });
}

function methodOrPropDecorator(...) {
  this.override('get', (val) => {
    // ...
  });
}
```