このすみ技術ろぐ

とあるWebエンジニアが、技術や趣味について書くブログです。

TypeScriptにおけるenumとconst enumの違いを、tscのコンパイル結果から確認してみる

オライリーの『プログラミングTypeScript』を読んでいるのですが、その中でenumconst enumの違いが述べられています。 内容が気になったので、実際にプログラムを書いて実験してみました。

実験内容

サンプルコード

次のサンプルコードを作成しました。 これをnpx tsc index.tsでコンパイルし、JavaScriptを出力します。

// enum
enum Ab {
     C = 1,
     D = "Two"
}
console.log("This is enum", Ab.C)
console.log("This is enum", Ab.D)

// const enum
const enum Ef {
     G = 3,
     H = "Four"
}
console.log("This is const enum", Ef.G)
console.log("This is const enum", Ef.H)

コンパイル結果

次の内容が実際のコンパイル結果として出力されたJavaScriptです。 なかなかに示唆的であることがわかります。

// enum
var Ab;
(function (Ab) {
    Ab[Ab["C"] = 1] = "C";
    Ab["D"] = "Two";
})(Ab || (Ab = {}));
console.log("This is enum", Ab.C);
console.log("This is enum", Ab.D);
console.log("This is const enum", 3 /* G */);
console.log("This is const enum", "Four" /* H */);

実験結果からわかったこと

enumは即席関数経由でオブジェクトが生成される

コンパイル後のJavasScriptから、通常のenumは即席関数を経由して、オブジェクトが生成されることがわかりました。

また、enumの値を数値(1)にしたケースと文字列(Two)にしたケースの違いも、示唆に富んでおりおもしろいです。 TSにおけるC = 1が、JSではAb[Ab["C"] = 1] = "C";となり、カッコ内で代入が実現しています。

/* Before(TypeScript) */
enum Ab {
     C = 1,
     D = "Two"
}
console.log("This is enum", Ab.C)
console.log("This is enum", Ab.D)
/* After(JavasScript) */
var Ab;
(function (Ab) {
    Ab[Ab["C"] = 1] = "C";
    Ab["D"] = "Two";
})(Ab || (Ab = {}));
console.log("This is enum", Ab.C);
console.log("This is enum", Ab.D);

const enumはインライン展開される

次にconst enumですが、これはインライン展開された結果、跡形もなく消え去っていることがわかります。

これは私の推測ですが、const enumは不変の存在なので、わざわざオブジェクトに展開する必要がないということだと思います。

/* Before(TypeScript) */
const enum Ef {
     G = 3,
     H = "Four"
}
console.log("This is const enum", Ef.G)
console.log("This is const enum", Ef.H)
/* After(JavasScript) */
console.log("This is const enum", 3 /* G */);
console.log("This is const enum", "Four" /* H */);

ちなみに余談ですが、// enumはコメントも含めてコンパイル結果に残っていたのですが、// const enumはコメントも一緒に消失していました。

tscのコンパイラーが、TypeScript内のコメントをどのように扱うのか、地味に気になります。

TypeScriptのenumは、そもそも使用するべきではない

なお『プログラミングTypeScript』では、そもそもenumを安全に使用するのは難しいとも書かれています。 何故かという理由は書くと長くなりそうですが、enumについて言及されている記事がいくつかありますので、参考としてご紹介します。

engineering.linecorp.com

www.kabuku.co.jp

qiita.com

まとめ

tscのコンパイル結果から、enumconst enumの違いを理解しました。 そもそもenumを使うべきではないと言ったら元も子もないですが、示唆的な違いを垣間見ることができ、おもしろかったです。

またtscのコンパイラーは、一般的なコンパイラーと異なり生成結果がJavasScriptなので、生成結果にも一定の可読性があります。 私たちがプログラミングしたTypeScriptが、実際にどのようなJavasScriptに変換されるのか、見比べてみるとおもしろいかもしれません。

プログラミングTypeScript ―スケールするJavaScriptアプリケーション開発

プログラミングTypeScript ―スケールするJavaScriptアプリケーション開発

  • 作者:Boris Cherny
  • 発売日: 2020/03/16
  • メディア: 単行本(ソフトカバー)