投稿日:2020年11月23日
トランスパイル先のコードを動かすJavaScriptエンジンごとにmoduleを正しく設定しましょう。
TypeScriptではES2015と同様にexportとついたものはモジュールとしてスコープであつかい、それ以外のものはグローバルとして扱います。TypeScriptのコードをトランスパイル後にどのモジュールパターンにするのかをtsconfigのmoduleという設定項目により設定します。
例えば、以下のような依存関係を持ったファイルがあるとします。
export default class Sample{
}
import Sample from "./sample";
class User {
constructor(){
var sample = new Sample();
console.log(sample);
}
}
var user = new User();
ここでtsconfig.jsonを以下のようなファイルとして作成します。
{
"compilerOptions": {
"module": "CommonJS",
"target": "ES2015"
}
}
このtsconfig.jsonはトランスパイル後のコードは、基本の文法はES2015でモジュール管理のやり方はCommonJSの方式で行うという設定になります。
nodejsのアプリケーションを作成する場合、この設定を使うかも。
トランスパイル後のコードは以下のようになります。
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class Sample {
}
exports.default = Sample;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const sample_1 = require("./sample");
class User {
constructor() {
var sample = new sample_1.default();
console.log(sample);
}
}
var user = new User();
では、例えば逆にブラウザで表示するフロントアプリケーションをトランスパイルする場合には以下のような設定にするかもしれません。
{
"compilerOptions": {
"module": "ES6",
"target": "ES2015"
}
}
この設定でトランスパイルします。
するとモジュールの管理が変わっているのが確認できます。
export default class Sample {
}
import Sample from "./sample";
class User {
constructor() {
var sample = new Sample();
console.log(sample);
}
}
var user = new User();
モジュールの管理をどの設定にしたいかはトランスパイル後のコードをどのエンジンで動かしたいかによりそうですね。
ES2020では以下の様なコード中での非同期のimportがサポートされています。
class MyIndex {
constructor(){
this.loadSample();
}
async loadSample(){
const Sample = await import("./sample");
const sample = new Sample.default();
}
}
const myindex = new MyIndex()
このコードをmodule:"ES2015"でトランスパイルしようとするとエラーになります。
動的インポートは、'--module' フラグが 'es2020'、'esnext'、'commonjs'、'amd'、'system'、'umd' に設定されている場合にのみサポートされます。ts(1323)
TypeScriptはECMAScript2015のモジュール管理になっています。
このようなimportをしたい場合にはtsconfigで対応するmoduleを指定して上げればOKです。
{
"compilerOptions": {
"module": "ES6",
"target": "ES2020"
}
}
この設定でトランスパイルするとTypeScriptのトランスパイラが次のように頑張ってawaitのimportをそれらしく実装してくれます(サンキューtsc!!!)。
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
class MyIndex {
constructor() {
this.loadSample();
}
loadSample() {
return __awaiter(this, void 0, void 0, function* () {
const Sample = yield import("./sample");
const sample = new Sample.default();
});
}
}
const myindex = new MyIndex();