Input Code
function observable() {}
class Example {
@observable()
toolbar = 'example';
}
export default Example;
JavaScript output
function observable() {}
var Example = (_dec = observable(), (_class = (_temp = function Example() {
(0, _classCallCheck2["default"])(this, Example);
(0, _initializerDefineProperty2["default"])(this, "toolbar", _descriptor, this);
}, _temp), (_descriptor = (0, _applyDecoratedDescriptor2["default"])(_class.prototype, "toolbar", [_dec], {
configurable: true,
enumerable: true,
writable: true,
initializer: function initializer() {
return 'example';
}
})), _class));
exports["default"] = Example;
TypeScript output
function observable() {}
var Example = function Example() {
(0, _classCallCheck2["default"])(this, Example);
this.toolbar = 'example';
};
__decorate([observable(), __metadata("design:type", Object)], Example.prototype, "toolbar", void 0);
exports["default"] = Example;
我們發(fā)現(xiàn)兩者編譯出的裝飾器屬性代碼并不相同石景。
現(xiàn)在我們創(chuàng)建一個javascript類ExampleEnhance
,繼承typescript類Example
变逃,并重寫裝飾器屬性toolbar
揽乱。
// This is javascript code, but class Example is typescript
class ExampleEnhance extends Example {
@observable()
toolbar = 'YY';
}
這時损拢,我們期望toolbar
的值為'YY'
掏秩,但是我們發(fā)現(xiàn)它的值仍然是'example'
蒙幻。
怎么辦?
我們有沒有辦法讓TypeScript
和JavaScript
裝飾器屬性編譯出來的代碼相同呢?
我們從TypeScript官方得到的回復是
TypeScript's decorators currently work differently from ES decorators, hence the experimental flag. If you need ES decorators you'll need to continue to process the code with Babel.
Because Typescript's decorator specification is not quite the same as anyone else's, they are always transformed.
You cannot do this right now unless you remove Typescript from the chain entirely. It always transforms decorators, leaving nothing left for Babel to transform.
因此,要讓兩者編譯出相同的代碼范嘱,我們必須要把typescript loader(比如awesome-typescript-loader
, ts-loader
)移除撕阎,而只使用babel
來轉(zhuǎn)換這兩類代碼棉饶。這里我們需要引入@babel/plugin-transform-typescript插件來處理TypeScript
。
配置babel
Install
npm install @babel/plugin-transform-typescript
babel.config.js
module.exports = {
presets: ['@babel/preset-typescript', '@babel/preset-react', '@babel/preset-env', 'mobx'],
plugins: [
['@babel/plugin-transform-typescript', { allowNamespaces: true }],
// ... other
]
}
webpack.config.js
module.exports = {
// ...
resolve: {
// Add '.ts' and '.tsx' as resolvable extensions.
extensions: ['.js', '.ts', '.tsx']
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'babel-loader',
},
]
}
};
那么发乔,如果改成這樣了栏尚,TypeScript
的類型檢測怎么辦呢抬虽?不是相當于廢了嗎?
你可以使用 TypeScript-Babel-Starter 或 fork-ts-checker-webpack-plugin來啟用TypeScript
類型檢測。
我們這里來說明一下如何使用fork-ts-checker-webpack-plugin
配置TypeScript類型檢查器
Install
npm install fork-ts-checker-webpack-plugin fork-ts-checker-notifier-webpack-plugin
webpack.config.js
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const ForkTsCheckerNotifierWebpackPlugin = require('fork-ts-checker-notifier-webpack-plugin');
module.exports = {
// ...
plugins: [
new ForkTsCheckerWebpackPlugin({
// 將async設(shè)為false弯菊,可以阻止Webpack的emit以等待類型檢查器/linter,并向Webpack的編譯添加錯誤才漆。
async: false
}),
// 將TypeScript類型檢查錯誤以彈框提示
// 如果fork-ts-checker-webpack-plugin的async為false時可以不用
// 否則建議使用,以方便發(fā)現(xiàn)錯誤
new ForkTsCheckerNotifierWebpackPlugin({
title: 'TypeScript',
excludeWarnings: true,
skipSuccessful: true,
}),
]
};