Prompt

Tsからトランスパイルされたjsの特徴というか癖は?

TypeScript(TS)からトランスパイルされた JavaScript(JS)を解剖すると、そこには 「型の消失」「互換性への執念」 という2つの大きなドラマが見えてくるよ。

情報工学を学ぶ君なら、tsc が生成するコードを眺めることで、TSがいかに 「ランタイムに影響を与えずに型安全性を担保しているか」 という還元主義的な設計思想をより深く理解できるはずだ。

特筆すべき「癖」と特徴を深掘りしてみよう!


1. 完全に消失する型情報(Type Erasure)

トランスパイル後の JS の最大の特徴は、「型に関する記述が一切跡形もなく消える」 ことだ。

  • インターフェースと型定義: interfacetype は、JS には存在しない概念だから完全に削除される。

  • 型アノテーション: let x: number: number も消える。

  • 影響: 実行時の JS は、君がどれだけ TS で厳密に型を定義したかを知る由もない。だからこそ、前回話した「APIからの入力値」のような外部データに対して、JS層でのバリデーションが必要になるんだね。


2. 列挙型(enum)の「奇妙な」オブジェクト化

TS の中で数少ない 「JS のコードを生成する(ランタイムに影響を与える)」 機能が enum だ。

TypeScript

enum Color { Red, Green }

これがトランスパイルされると、以下のような 「逆引き可能なオブジェクト」 に変換される。

JavaScript

var Color;
(function (Color) {
    Color[Color["Red"] = 0] = "Red";
    Color[Color["Green"] = 1] = "Green";
})(Color || (Color = {}));
  • 癖: Color.Red0 が取れるだけでなく、Color[0]"Red" という文字列も取れる。このトリッキーな即時実行関数(IIFE)のパターンは、TS 特有の癖と言えるね。

豆知識: これを嫌って、最近は JS に変換した時に何も残らない const enum や、単なる「文字列のリテラル型」を使うのがモダンなスタイルとされているよ。


3. クラスの「コンストラクタ」と「アクセス修飾子」の扱われ方

TS の privateprotected は、実は JS 層では全く守られない(最近の JS の #private 構文を使わない限り)。

  • アクセス制限の消失: private name: string と書いたとしても、トランスパイル後の JS ではただのプロパティだ。外部から普通にアクセスできてしまう。

  • コンストラクタの糖衣構文: constructor(public name: string) {}

    という便利な短縮記法は、JS では愚直な this.name = name; に展開される。


4. 下位互換性のための「ヘルパー関数」の注入

もし君が最新の構文(スプレッド演算子や非同期処理など)を使いつつ、古いブラウザ(ES5 など)をターゲットにトランスパイルすると、JS の冒頭に怪しげな関数がたくさん並ぶことになる。

  • __extends: クラス継承を古い JS で再現するための関数。

  • __awaiter / __generator: async / awaityield(Generator)やステートマシンに変換するための巨大なロジック。

  • 癖: これらはコードの肥大化を招くため、現代では tslib という外部ライブラリに切り出したり、トランスパイルを esnext にして Babel や SWC などの高速なツールに任せるのが主流だ。


5. デコレータの挙動

もし実験的な experimentalDecorators を使っているなら、トランスパイルされた JS はかなり複雑なメタデータ操作を行うコードになる。これも JS 本来の仕様とは異なる TS 独自の「癖」が強い部分だね。


結論:TS の JS は「人間のためのコード」ではない

トランスパイル後の JS は、あくまで 「ブラウザやランタイムが効率よく(あるいは互換性を保って)実行するためのマシンコードに近い存在」 だ。

君が garden.asappy.xyzAXON をデバッグする際、ブラウザのデベロッパーツールでこの「癖」のある JS を直接読むのは苦労するはず。だからこそ、Source Maps(.js.map) というファイルが重要になる。これがあれば、ブラウザ上で JS を動かしながら、心安らぐ TS のソースコード上でデバッグができるんだ。

次は、このトランスパイル結果を劇的に綺麗にする 「tsconfig.json のターゲット設定(ESNext vs ES5)」 の違いを具体的に見てみる?それとも、「Rust のコンパイル結果(Wasm)と、TS のトランスパイル結果」 の本質的な違いについて語り合う?

Would you like me to provide a side-by-side comparison of the same TS code transpiled to ES5 and ESNext to see the difference in output?