简体   繁体   中英

Are babel decorators the same as TypeScript's?

我使用TypeScript进行了很多编码,但不太熟悉,我知道TypeScript如何在装饰器上工作,而babel也支持装饰器,它们的行为是否相同?

Yes, they are the same, in a sense that they produce the same behavior, but they have different implementations.

Both follow ECMAScript specifications and bring features early to us. You can expect what is on both of them to probably be supported by node or the browser in the future.

Code:

function f() {
  console.log("f(): evaluated");
  return function (target, propertyKey, descriptor) {
      console.log("f(): called");
  }
}

function g() {
  console.log("g(): evaluated");
  return function (target, propertyKey, descriptor) {
      console.log("g(): called");
  }
}

class C {
  @f()
  @g()
  method() {}
}

new C().method();

TypeScript output:

var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
function f() {
    console.log("f(): evaluated");
    return function (target, propertyKey, descriptor) {
        console.log("f(): called");
    };
}
function g() {
    console.log("g(): evaluated");
    return function (target, propertyKey, descriptor) {
        console.log("g(): called");
    };
}
class C {
    method() { }
}
__decorate([
    f(),
    g()
], C.prototype, "method", null);
new C().method();

Babel output:

"use strict";

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _dec, _dec2, _desc, _value, _class;

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) {
  var desc = {};
  Object['ke' + 'ys'](descriptor).forEach(function (key) {
    desc[key] = descriptor[key];
  });
  desc.enumerable = !!desc.enumerable;
  desc.configurable = !!desc.configurable;

  if ('value' in desc || desc.initializer) {
    desc.writable = true;
  }

  desc = decorators.slice().reverse().reduce(function (desc, decorator) {
    return decorator(target, property, desc) || desc;
  }, desc);

  if (context && desc.initializer !== void 0) {
    desc.value = desc.initializer ? desc.initializer.call(context) : void 0;
    desc.initializer = undefined;
  }

  if (desc.initializer === void 0) {
    Object['define' + 'Property'](target, property, desc);
    desc = null;
  }

  return desc;
}

function f() {
  console.log("f(): evaluated");
  return function (target, propertyKey, descriptor) {
    console.log("f(): called");
  };
}

function g() {
  console.log("g(): evaluated");
  return function (target, propertyKey, descriptor) {
    console.log("g(): called");
  };
}

var C = (_dec = f(), _dec2 = g(), (_class = function () {
  function C() {
    _classCallCheck(this, C);
  }

  _createClass(C, [{
    key: "method",
    value: function method() {}
  }]);

  return C;
}(), (_applyDecoratedDescriptor(_class.prototype, "method", [_dec, _dec2], Object.getOwnPropertyDescriptor(_class.prototype, "method"), _class.prototype)), _class));


new C().method();

Output after run:

> ts-node ts-example.ts
f(): evaluated
g(): evaluated
g(): called
f(): called

> node babel-example.js
f(): evaluated
g(): evaluated
g(): called
f(): called

Not sure of the latest state of the decorators, but half year ago Babel and TypeScript decorators where different in behavior in some cases. Decorators is not a specification yet, it is only Stage 2 . That's why in TypeScript decorators is an experimental feature.

For example, non enumerable from core-decorators didn't work in TypeScript some time ago. And almost all decorators, that applied to the fields.

So the answer is: "they are similar, but not equal". Do not suggest, that you write one decorator, and it will work similar in babel and TypeScript. Until it will be standardized and realizations will match the standard.

No, they are different. Babel don't support parameter decorators, and TS's property decorators don't support the initializer for a property.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM