2024/01/26

 先日購入した「TypeScriptとReact/Next.jsでつくる実践webアプリケーション開発」で、TSやフレームワークであるNext.jsを触れつつ実際に開発を経験してみる。その学習記録。
 またうひょ氏こと鈴木僚太氏著の「プロを目指す人のためのTypeScript入門」も併読している。TSの挙動や仕様を知るにはうひょ氏著作を、実際に作ってみる教科書としてアプリケーション開発のほうを拝読している。

 記事内容は学習その記録。

 

「TypeScriptとReact/Next.jsでつくる実践webアプリケーション開発」chapter2.6では各種開発時の設定についての節がある。

 中でもtsconfig.jsonファイルのコンパイルに必要なオプションに関して調べたものを以下書き記す。

 公式リファレンスこちらのQiita記事を参考にさせてもらったため、随所引用させて頂く。

 また調べた内容は本書に出てきたオプションのみ。

 

 以下compileOptions配下の各フィールド。

 

 targetフィールド

 ここで指定するのはどのECMAscript、つまりJSのバージョンなのかという指定。コンパイルの際のバージョンとなるため、Qiita記事ではBabel的役割とも記されている。

 公式曰く、最新のブラウザはES6までのすべての機能をサポートしているため、ES6にすることを推奨しているようだ。

 古いバージョンにすることもできるだろうが、新しくプロダクト?プロジェクト?をスタートする際は新しいバージョンである方が良いと思った。

 またESNextにするとES6であると同時に、次にくるであろう仕様などを踏まえたバージョンにすることができる。

 本書ではES5と記述がなっているが、6で問題ないだろう。

 

 libフィールド

 コンパイルの際の組み込みライブラリを指定するフィールド。targetで指定したものに組み込まれているものは暗黙的にここにも入るらしい。配列として複数列挙が可能。

 そのため、JSのバージョンだけではどうにもならないものを追加でコンパイルするためぶち込む。公式リファレンスによればブラウザ環境のdocumentなどがあるようだ。

 実際本書ではDOM、DOM.Iterable、ESNextがここには入っている。ブラウザ環境を再現するためにDOMはいるだろうし、DOM.Iterableもおそらくいるのだろう。

 ただし、明示的に指定すると、暗黙的に指定されていたものはオートで指定されなくなるので、必要なものは全部列挙する必要があるらしい。

 ブラウザ提供のライブラリはここで読み込むため、必須のフィールドと言える、と思う。

 

 allowJsフィールド

 プロジェクト内で、.jsと.jsxファイルをインポート可能にするするかどうかのフィールド。Qiita記事によれば、これによってコンパイル対象となる。

 公式リファレンスを読むとTSファイルはデフォルトでインポート可能で、JSも同様にインポートするか決められる。

 筆者はそもそもTSの開発経験どころか、開発そのものの経験がないため分からないが、自分で作ったファイルのインポート/エクスポートのみならず、ライブラリを使う際にもここはtrueでいいのではないだろうか。

 

 skipLibCheckフィールド

 Qiita記事には書かれていないため主要ではないオプションなのだろうか?

 公式リファレンスによれば「宣言ファイルの型チェックをスキップする」らしい。

 型システム精度は犠牲になるがコンパイルの時間を節約できるらしい。

 すべてのファイルを完全な型チェックをするのではなく、d.tsファイルによる型とソースコード内の型チェックで済ませるもののようだ。

 何やら複雑そうなことがかいてある。TSのバージョン更新によって起こる諸問題をいったん無視するようなオプション……?

 

 strictフィールド

 これをtrue(オン)にすると関係するstrictオプションが全部true(オン)になるようだ。関係するオプション(ファミリオプション?)は8つくらいある。名前の通りめっちゃ厳格なんだろうな。

 オフにしておけば、個別のstrictオプションを別個設定できるようだ。

 本書ではfalse(オフ)になっている。どっちにすべきかは分からんけどとりあえずオンでもよさそう。

 

 strictNullCheckフィールド

 これをオンにすると、nullまたはundefinedなアクセスに対してエラーを吐くようになる。

 例えばオブジェクトにアクセスした時などに「trueになる何かが保証されていないなら、エラーを出す」という感じ。

 おそらくは型によって中身を保証しろ、というモードだろうか。

 一応、これをオンにしていてもアクセスの際に!(non-null assertion)演算子をつければ回避できるらしいが、TSのコンセプトとそぐわないため基本的に使わないテクニックだろう。

 オンにしていてよさそうだ。

 

 forceConsistentCasingInFileNamesフィールド

 これはインポートする際の名前と、インポート元のファイル名を参照して「お前ちゃんと大文字小文字もちゃんとあってんだろうな」とチェックするオプション。
 例えば、「HogeFoo」というファイルを「hogeFoo」とインポートすると怒られる。

 名前の通り「ファイル名において一貫性あるケースを強制する」オプション。

 大文字小文字での間違いなんてしょうもないし、それが潰せるなら結構いいのでは。

 オンで問題はないと思う。

 

 noEmitフィールド

 TSCを走らせた際に、結果であるJSファイルを出力するかしないかのオプション。

 発する(emit)にnoがついてるので名前の通りと言える。

 これをオンにすることでBabelなどの別のツールがコンパイルを担当することになるだろう。
 あくまでTSの型チェックだけを目的にする場合にも有効。

 これいまのところオンとオフどっちにすべきか分からん。本書ではtrueになってるので出力はされていないが。

 

 esModuleInteropフィールド

 翻訳によればESモジュールの相互運用性という部分。

 古いインポート方法を今の記法に直してくれるオプション、のはず。

 CommonJS/AMD/UMDのモジュールをES6モジュールと同様に扱うらしい。

 筆者はなじみがないが、古いJSではモジュール機能がなく、require関数を用いてインポートしていた。新しい記法を用いても古い古い記法でも通じるように直してくれる…んだと思う。

 Qiita記事には載っていない。

 オンで問題ない、よな?

 

 moduleフィールド

 モジュールのシステムはどの記法とかバージョンにする?っていう項目のようだ。

 CommonJSやES2015、ESNextなどtargetフィールドみたいな感じで指定してやる必要がある。

 モジュールって何回も出てくる上にモジュールだけのフィールドもあってびっくりした。

 モジュールっていっぱい出てくる上にまたモジュールかよとびっくりした。

 とりあえずES6とかESNextでいいんじゃないかなぁ……。

 というか調べててES5が2009年、ES6で2015年てびっくりした。

 

 moduleResolutionフィールド

 TSCがモジュールを解決(読み込む?)際の方法を指定するフィールド。

 またモジュールかよ!と思ったけど、これはTSコンパイラ自身への設定のようだ。

 オンオフではなく既定の文字列を指定してやる。

 何やらモジュールインポートがパスを指定してやる相対的、シンプルに名前だけ書く非相対的インポートの解決方法に関するものらしい。なんか難しい。

 デフォルトがnodeであり、他にもbundlerやclassicがあるようだがnodeでよさそうだ……。

 

 resolveJsonModuleフィールド

 .jsonを含むモジュールをインポートできるようになるオプション。デフォルトだとできないんかーい。

 オンにすることでJSONが使える。便利。
 しかし公式で静的なJSON形状に基づいたタイプの生成が含まれる、と書いてある。つまりJSONごとに形状に応じた型が生成されるのか…?deepl翻訳だから分からん。

 Qiitaにも乗っていなかった。

 オンで問題はないだろう。逆にオフだとJSONなんか読み込まねぇぞとか起こりそう。

 

 isolatedModulesフィールド

 Deeplによると分離されたモジュールらしい。これをオンにすると単一ファイルのトランスコンパイルプロセスで正しく解釈できない特定のコードを記述した場合に警告するようになる、らしい。分かんねぇ。

 Qiita曰く、コンパイル対象のファイル感の関係性を無視し、すべてのファイルを単一のモジュールとしてコンパイルする、らしい。分からん。

 trueにした場合、コンパイル対象すべてがexportを含む対象となるらしい。

 また、インポートした型をそのままexportする?型re-exportもエラーが出る。

 本書ではtrueになっている。
 インポートエクスポートを繰り返すことで、fluxになるからか?

 

 jsxフィールド

 コンパイルの結果出てくるJSファイルにJSXがどう反映されるかのフィールド。tsxファイルをjsxやjsにコンパイルする際の出力形式。

 ただQiita記事がdeclareキーワードなども使っており、ずぶの素人である自分には些か難しく感じる。

 preserveはjsxをそのまま地保持するため、tscコンパイラ以外にコンパイルさせる場合に有効なようだ。

 ただ、型としてraectがインストールされているならjsxの型は必要ない?(--savedevフラグ付きで@types/reactをインストール)

 preserveかreactでいいのだろうか。本書ではpreserveになってる。

 TSにおけるJSX記事はここが分かりやすいそうだ。ってうひょさんじゃないか。

 

 baseurlフィールド

 非相対的(non-relative)なインポートにおいて、相対的なカレントディレクトリがどこかを指定する。

 そのため、パスを記述してインポートする相対的(relative)インポートには影響が出ないようだ。

 これはnode_modulesの検索よりも優先されるようだ。

 とりあえず本書ではsrcディレクトリが指定されている。自分はtsconfig.jsonファイルがルートディレクトリにあるため、とりあえずパスで./srcとしているが変わらないのかな。変わるのかな。

 

 以下、compilerOptionsフィールドを抜け、includeとexcludeフィールドへ。

 

 includeフィールド

 ここには配列で記述でき、コンパイル対象となるファイルやその条件を記述する。

 正規表現じみた*や?などのワイルドカード?というのが仕様できるらしい。そのため、コンパイル対象を全部相対パスなどで記述する必要はない。

 

 excludeフィールド

 逆にコンパイル時に除外されるファイルを指定するフィールド。

 だが正確には「エントリーファイルからは除外するけど、それ以外には寛容しない」。

 babelなどのツールは複数のファイルをまとめて単一のファイルを出力するが、その起点となるファイル(エントリーファイル)からは読み込まないだけで、エントリーがインポートしたファイルそのものが除外ファイルを更にインポートしている場合、結果読み込まれる。

 読み込むファイルの優先度としては、encludeよりも高いようだが、filesという設定がありそこにあれば除外されていてもコンパイル対象になるらしい。

 難しい…。

 

 他にも本書ではprettier、ESlintなどに触れているが割愛。

 本節をもってchapter2は終わり、chapter3からはReactを用いた開発が始まる。