TypeScript について調べたことなどのメモ
TypeScript を書いているなら esbuild が型チェックしないので tsc
を併用しないといけないことは常識らしいのだが、既に環境構築が終わった状態 or さくっと環境構築できるやつを使って何となく環境構築した状態で、雰囲気でしか TypeScript を書いたことのない人間だとそもそも tsc
使ったことないという状況が起こりうる。
いつまでも雰囲気で TypeScript を書いているから重大なやらかしを起こしてしまうので、過去の Module Bundler の歴史的な部分は別の人がまとめた記事を読むとして、今使っているものについては自分で調べた。
TypeScript
Microsoft が開発したプログラミング言語である。
https://www.typescriptlang.org/
What is JavaScript? A Brief History
https://www.typescriptlang.org/docs/handbook/typescript-from-scratch.html
意訳で要約する。
- JavaScript(ECMAScript としても知られる)はブラウザのためのシンプルなスクリプト言語として始まった
- その後色々あって何百万行ものアプリケーションを書くための本格的なツールに成長したのだが、小規模なプログラムなら何とかなる奇妙な挙動が、大規模アプリケーションでは深刻なバグを引き起こすことになった
- 幾つかの言語では JavaScript でバグを引き起こすような挙動を静的検査で検出する
- 操作される値の種類によって、何がエラーで何がエラーでないかを判断することを静的型検査という
- TypeScript は静的型検査を行う
- TypeScript は JavaScript の「型付」スーパーセットなので、JS のシンタックスは TS でも有効だが、「どのような種類の値が使われるか」に関する新たなルールが追加されている
- TypeScript は JavaScript の実行時の挙動を変更しない。JavaScript のコードを TypeScript に持ってきたとき、TypeSript がエラーとして検出するコードが含まれていたとしても、そのコードの実行時の挙動は変わらない。
- TypeScript のコンパイラはコードの検査後、型情報を削除して JS コードを作成する
Why does TypeScript exist?
https://www.typescriptlang.org/why-create-typescript
前の内容と被る部分もあるが意訳で要約する。
- JavaScript は
var name = "Danger"
と宣言したname
に何でも(数字でも、日付の配列でも)入れられるが、たとえば Java はString name = "Danger";
と宣言したname
にはString
しか入れられない- これら二つの間に優劣は無くて、ただ単に JavaScript や Java が作られた当時、二つの言語の目的が違っていただけである
- JavaScript は Web サイト上でのちょっとしたインタラクションを書くための小さなプログラミング言語として設計されたので、読みやすくて小さいコードになることを優先した
- Java は様々なコンピュータ上で動く複雑なアプリケーションを作るために生まれたので、変数の値を明示することをプログラマーに求めていた
- 90 年代、もしかしたら 5-10 年前までは JavaScript は Web サイトのフロントエンドの領域に使われていて、その規模や複雑さを考えても型がないことは問題なかった
- でも今日では JavaScript はほとんどどこでも使われるようになって、構築も理解も複雑になった
- TypeScript は JavaScript の拡張だけを目的にしているので、JavaScript のコードはそのまま TypeScript として動作する
- TypeScript は、JavaScript に「どのような種類のデータが使われるか」を明示する拡張機能を追加する(ちょっと Java に似ている)
- 型注釈があることによって、大量のファイルの中の一つに変更を加えたときに他が壊れていないか検証する時間を短縮でき、大きなアプリケーションを作りやすくなる
tsc, the TypeScript compiler
https://www.typescriptlang.org/docs/handbook/2/basic-types.html
tsc
が TypeScript から JavaScript のコードを作るコンパイラで、型検査をしてくれた後に JS ファイルが生成される。
諸々オプションを指定できる。
noEmit
は型検査だけするので、Babel などの他のツールで JS ファイルに変換することができるようになる。
esbuild
Major features:
- Extreme speed without needing a cache
- JavaScript, CSS, TypeScript, and JSX built-in
- A straightforward API for CLI, JS, and Go
- Bundles ESM and CommonJS modules
- Tree shaking, minification, and source maps
- Local server, watch mode, and plugins
TYpeScript については content-types/#typescriptに記載がある。
esbuild does not do any type checking so you will still need to run
tsc -noEmit
in parallel with esbuild to check types.
私が何となく環境構築したフロントエンド(Next.js)
そもそも Next.js では誰がトランスパイルしているのかを知らないので調べた。
https://nextjs.org/docs/basic-features/typescript
Starting in v12.0.0, Next.js uses SWC by default to compile TypeScript and TSX for faster builds.
Next.js will use Babel to handle TypeScript if .babelrc is present.
私の環境には .babelrc が無いので SWC が使われているはずだが、詳しく見ていくと
The Next.js Compiler, written in Rust using SWC, allows Next.js to transform and minify your JavaScript code for production.
とのことなので SWC を使って作られた別物のようである。
Next.js Compiler においては next.config.js でコンパイラの設定を書ける。
https://nextjs.org/docs/advanced-features/compiler
Next.js Compiler が tsconfig.json の中身を見てターゲットを決めているのか調べたけどわからない。
Next.js Compiler においては SWC の設定ファイルである .swcrc は使えないし、tsconfig.json 以外に指定する箇所がなさそうな感じがするが……。
後述の通り SWC は型チェックをしていないと思われるのだが、Next.js は型チェックをしている。
https://nextjs.org/docs/basic-features/typescript#ignoring-typescript-errors
Next.js fails your production build (next build) when TypeScript errors are present in your project.
SWC
SWC can be used for both compilation and bundling. For compilation, it takes JavaScript / TypeScript files using modern JavaScript features and outputs valid code that is supported by all major browsers.
SWC is designed to be extensible. Currently, there is support for:
- Compilation
- Bundling (swcpack, under development)
- Minification
- Transforming with WebAssembly
- Usage inside webpack (swc-loader)
- Improving Jest performance (@swc/jest)
- Custom Plugins
https://swc.rs/blog/swc-1#typescript-support
たぶん型チェックはしていない。