tsconfig.jsonを設定する

Node.jsはそれ自身ではTypeScriptをサポートしているわけではないため、TypeScriptの導入をする時はTypeScriptの設定ファイルであるtsconfig.jsonが必要です。

初めてのtsconfig.json

typescriptpackage.jsondependenciesに入っているプロジェクトで以下を実行してください。

npx tsc --init

typescriptがglobal installしてあれば下記のように実行することもできます。

tsc --init

tsconfig.jsonが作成されます。すでにtsconfig.jsonがある時は上書きされませんのでいったん既存のtsconfig.jsonを別名に変更してから実行など、一度tsconfig.jsonと名のつくファイルが存在しないようにしてください。

公式にあるtsconfig.jsonの説明はこちらです。

全てのオプションの解説をすると余白が足りないので、ここでは用途を抽出して、以下の観点で説明します。

  • targetの決め方

  • フロントエンドとバックエンドで変えるべき設定

  • いま一からつくるならどうすればいいか(仮)

target

TypeScriptは最終的にJavaScriptにトランスパイルされます。このオプションはその時に、どのバージョンのJavaScript向けに出力するかといったものです。

JavaScriptも時代とともに進化をして、既存のオブジェクトに新しいメソッドが追加されることがあります。新しく追加されたメソッドは出力するJavaScriptのバージョンがそのメソッドをサポートしていない時はすなわち使えない、というわけではなくTypeScript側で擬似的に再現して補完してくれます。

このような最新バージョンにはある、または現在実装には至っていないが提案中(proposal)である機能を取り入れて使えるようにする物を通称polyfillと言います。polyfillについて更に詳しく知りたい方は、What is a polyfill? (この単語の創案者である Remy Sharp による記事)をご覧ください。

lib

使いたいtargetには使いたい機能がない、でも使いたい。そのような時はlibオプションを指定することで使うことができるようになります。libは必ず指定する必要はありません。targetを指定すればそのtargetで使われている標準ライブラリを指定する必要はありません。指定したtargetでは実装されていないライブラリや、必要がなく除外したいライブラリを外したい時に使用します。

指定は必ずしも必要ないとは申し上げましたが、Node.jsでは構文(syntax)のサポートよりもAPIのサポートが先に行われることがあるためtargetではまだサポートしていないがNode.jsで使えるようになっているlibを指定する用途があります。

targetは何を指定したらいいか

あえて古いコードで動かしている、または古いNode.jsを使っているといった事情がなければ最新に近い物を指定することは問題ありません。2020/09現在はLTSとしてNode.js 14.xが登場しています。Node.js 14.xであればtarget: "es2020"は無難な選択肢です。

またBabelなどの専用のコンパイラやmodule bundlerに処理を任せたい場合はtarget: "esnext"をしてそこからバージョンに合わせたコンパイルを各々にお願いすることになります。

フロントエンドとバックエンド

フロントエンドとバックエンドはモジュールの読み込み方法が異なっています。詳細はimport / export / requireの頁をご覧ください。以下の設定は使う場面で切り替えるべき項目です。

module

モジュール読み込みの仕組みが異なっているライブラリの互換性一般的にはないものと考えてください。そしてこれはフロントエンドとバックエンドでは異なります

commonjs

バックエンド(サーバーサイド)で使われている解決方法です。作成しているモジュールやパッケージがバックエンドでの動作だけを保証したい場合は最も無難な選択です。

es2015, es2020, esnext

通称esmoduleと呼ばれる解決方法です。フロントエンドで使われています。Node.jsは13.2.0でバックエンドでも同様にこのモジュール解決方法をサポートしましたが、現状対応しているパッケージは少なく、使いづらい印象です。

このような違いがあるため、使う場面がバックエンドならcommonjsを、フロントエンドならes2015, es2020, esnextを指定することが望ましいです。

2020年版スクラッチから作るなら

スクラッチから作るということは現在の資産との整合性の都合、しがらみが一切ない状態です。ここから作るならこれだけは満たしておけば型に満ちたプログラミングができるのではという紹介です。

しがらみがないという条件のもと、Node.jsは14.xを使っているものとします。

バックエンドの場合

{
"compilerOptions": {
"target": "es2020",
"module": "commonjs",
"lib": [
"es2020"
],
"sourceMap": true,
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"moduleResolution": "node",
"baseUrl": "src",
"esModuleInterop": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": [
"src/**/*"
],
"exclude": [
"dist",
"node_modules"
],
"compileOnSave": false
}

フロントエンドの場合

{
"compilerOptions": {
"target": "es2020",
"module": "esnext",
"lib": [
"es2020",
"dom"
],
"jsx": "react",
"sourceMap": true,
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"moduleResolution": "node",
"baseUrl": "src",
"esModuleInterop": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": [
"src/**/*"
],
"exclude": [
"dist",
"node_modules"
],
"compileOnSave": false
}

異なる箇所について

これらの設定で異なるのはmodule, lib, jsxです。フロントエンドであればlibdomを加え、さらにjsxを使うのであればどのミドルウェアを使うのかを設定します。