Panda Noir

JavaScript の限界を究めるブログでした。最近はいろんな分野を幅広めに書いてます。

TypeScript で polyfill やトランスパイルをどう扱えばいいか

In short: ES2017 が動く環境を対象にビルドするなら

例として ES2017 が動く環境を対象にビルドを考える。

  • tsconfig の target に es2017 を指定
  • tsconfig の lib に es2017 を指定
    • dom も必要であれば加える
    • 他の機能、例えば Array.prototype.flat が欲しくなったら、手動で polyfill を追加した後に tsconfig の lib に es2019.array を加える
  • eslint-plugin-compat を導入する
    • サポート対象のブラウザ環境で Web API が使えるかどうかを確認するために使う
    • polyfill の入れ忘れ防止になる

こうすれば、ES2017 より後に追加されたシンタックスはトランスパイルされるので安心して使える。もし ES2017 より後に追加された標準組み込みオブジェクトやメソッドを使っていたらコンパイルが落ちるし、各種 Web API は eslint-plugin-compat が弾いてくれる。だいぶ盤石なはず。

整理: ECMAScript に含まれるもの、含まれないもの

まず、「ECMAScript」がどこまでを含んでいるかをまとめた。

  • 標準組み込みオブジェクトは ECMAScript に含まれる(Promise や Math、String など)
  • 各種シンタックスやオブジェクトのメソッドも ECMAScript に含まれる(オプショナルチェーン演算子や Array.prototype.flat など)
  • Web API は ECMAScript に含まれない(WindowインターフェイスやDOM API、IntersectionObserver など)
    • DOM API は WHATWG が定める DOM Living Standard に規定されている。
    • IntersectionObserver は W3C が定めている。
    • History API は HTML Living Standard が定めている。

まとめると標準組み込みオブジェクト、シンタックス、メソッドが ECMAScript に含まれていて、Web API は含まれていない。TypeScript は基本的に ECMAScript だけを扱っている。Web API には関与していない。

TypeScript のコンパイル時の役割

TypeScript はコンパイル時に大まかに2つの役割を果たす。

  • シンタックスのトランスパイル (オプショナルチェーン演算子(?.)など)
  • ECMAScript に入っている標準組み込みオブジェクトやメソッドが target、lib のバージョン内にない場合にコンパイルを失敗させる

TypeScript は polyfill を入れたりはしないが、target、lib のバージョン内にない標準組み込みオブジェクトがを使っていたらコンパイルを通さない。この場合、手動で polyfill を入れて動くようにした後に lib へ該当するものを追加してコンパイルを通るようにする。

上記の通り、TypeScript は基本的に Web API について関知しない。例えば lib: ["dom"] を指定すると、target のバージョンに関わらず IntersectionObserver が扱えてしまう。これ以上はどうしようもないので eslint-plugin-compat で対処する。