@slietar/decorate

An advanced __decorate helper for the TypeScript compiler

Usage no npm install needed!

<script type="module">
  import slietarDecorate from 'https://cdn.skypack.dev/@slietar/decorate';
</script>

README

Decorate

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:

$ npm install @slietar/decorate --save-dev

By overriding __decorate and __param

In a JS file:

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:

$ tsc --experimentalDecorators --noEmitHelpers --target ES5 # or ES6

By overriding Reflect.decorate (no support for __param)

// 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)

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

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) => {
    // ...
  });
}