I code with TypeScript a lot, but less babel, I know how TypeScript works on decorators, and babel also support decorators, do they act the same?
Conclusion. Having Babel and TypeScript do part of the source transform seems unnecessarily complicated. So, if you are using both, it is better to use Babel for transpiling and the TypeScript compiler for type checking.
Babel for transpiling, tsc for types ts file generation. By using babel's support for TypeScript, you get the ability to work with existing build pipelines and are more likely to have a faster JS emit time because Babel does not type check your code.
A Decorator is a special kind of declaration that can be attached to a class declaration, method, accessor, property, or parameter. Decorators use the form @expression , where expression must evaluate to a function that will be called at runtime with information about the decorated declaration.
JavaScript decorators are a relatively new feature in JavaScript that allows adding new behavior to existing functions and objects without modifying their underlying code. You can achieve it by using a special syntax that uses an @ symbol before the function name or object key.
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
No, they are different. Babel don't support parameter decorators, and TS's property decorators don't support the initializer for a property.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With