※このブログではサーバー運用、技術の検証等の費用のため広告をいれています。
記事が見づらいなどの問題がありましたらContactからお知らせください。


【TypeScript】tsconfig.jsonのmoduleについて解説

モジュール TypeScript module tsconfig.json TSConfig

投稿日:2020年11月23日

このエントリーをはてなブックマークに追加
トランスパイル先のコードを動かすJavaScriptエンジンごとにmoduleを正しく設定しましょう。

実践

Javascriptのモジュール

JavaScriptでは各プログラムの分割をimportexportによるモジュールという機能によって実現させています。基本的にモダンブラウザはすべてモジュール機能に対応しています(Internet ExplolerはNo)。

モジュールは初期のJavaScriptには存在せず、言語仕様のアップデートで徐々に進化していった機能です。そのため、使用できるモジュールの文法は言語の各バージョンごとに異なります。

例えばES6からはモジュール化に"use strict"が要らなくなったり、ES2020からはawait文を使ったコード中のモジュールの読み込みができるようになったりしています。

tsconfigのmodule

TypeScriptではES2015と同様にexportとついたものはモジュールとしてスコープであつかい、それ以外のものはグローバルとして扱います。TypeScriptのコードをトランスパイル後にどのモジュールパターンにするのかをtsconfigmoduleという設定項目により設定します。

例えば、以下のような依存関係を持ったファイルがあるとします。

sample.ts
export default class Sample{   
}
user.ts
import Sample from "./sample";

class User {
    constructor(){
        var sample = new Sample();
        console.log(sample);
    }
}

var user = new User();

ここでtsconfig.jsonを以下のようなファイルとして作成します。

tsconfig.json
{
    "compilerOptions": {
        "module": "CommonJS", 
        "target": "ES2015"
    }
}

このtsconfig.jsonはトランスパイル後のコードは、基本の文法はES2015でモジュール管理のやり方はCommonJSの方式で行うという設定になります。

nodejsのアプリケーションを作成する場合、この設定を使うかも。

トランスパイル後のコードは以下のようになります。

sample.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class Sample {
}
exports.default = Sample;
user.js
"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();

では、例えば逆にブラウザで表示するフロントアプリケーションをトランスパイルする場合には以下のような設定にするかもしれません。

tsconfig.json
{
    "compilerOptions": {
        "module": "ES6", 
        "target": "ES2015"
    }
}

この設定でトランスパイルします。

するとモジュールの管理が変わっているのが確認できます。

sample.js
export default class Sample {
}
user.js
import Sample from "./sample";
class User {
    constructor() {
        var sample = new Sample();
        console.log(sample);
    }
}
var user = new User();

モジュールの管理をどの設定にしたいかはトランスパイル後のコードをどのエンジンで動かしたいかによりそうですね。

TypeScriptでサポートされていない管理方法の場合

ES2020では以下の様なコード中での非同期のimportがサポートされています。

index.ts
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です。

tsconfig.json
{
    "compilerOptions": {
        "module": "ES6", 
        "target": "ES2020"
    }
}

この設定でトランスパイルするとTypeScriptのトランスパイラが次のように頑張ってawaitimportをそれらしく実装してくれます(サンキューtsc!!!)。

index.js
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();
このエントリーをはてなブックマークに追加


関連記事

記事へのコメント