Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
tsconfig.jsonの設定を見直そう!フロントエンド向け 2024夏
Search
uhyo
August 06, 2024
Technology
26
12k
tsconfig.jsonの設定を見直そう! フロントエンド向け 2024夏
2024-08-06 TSKaigi サブイベント #1 フロントエンド
uhyo
August 06, 2024
Tweet
Share
More Decks by uhyo
See All by uhyo
libsyncrpcってなに?
uhyo
0
610
Next.jsと状態管理のプラクティス
uhyo
7
9.1k
10ヶ月かけてstyled-components v4からv5にアップデートした話
uhyo
5
620
更新系と状態
uhyo
8
3.6k
React 19アップデートのために必要なこと
uhyo
8
2.6k
color-scheme: light dark; を完全に理解する
uhyo
8
690
React 19 + Jotaiを試して気づいた注意点
uhyo
9
3.5k
TypeScriptの次なる大進化なるか!? 条件型を返り値とする関数の型推論
uhyo
3
3.3k
tsconfig.jsonの最近の新機能 ファイルパス編
uhyo
8
4.6k
Other Decks in Technology
See All in Technology
開発と脆弱性と脆弱性診断についての話
su3158
1
920
LLM時代の検索とコンテキストエンジニアリング
shibuiwilliam
2
1k
メルカリIBIS:AIが拓く次世代インシデント対応
0gm
2
490
我々は雰囲気で仕事をしている / How can we do vibe coding as well
naospon
2
170
20250807 Applied Engineer Open House
sakana_ai
PRO
2
670
Amazon Bedrock AgentCore でプロモーション用動画生成エージェントを開発する
nasuvitz
6
340
モダンな現場と従来型の組織——そこに生じる "不整合" を解消してこそチームがパフォーマンスを発揮できる / Team-oriented Organization Design 20250825
mtx2s
2
180
UDDのススメ - 拡張版 -
maguroalternative
1
670
フルカイテン株式会社 エンジニア向け採用資料
fullkaiten
0
8.5k
ECS モニタリング手法大整理
yendoooo
1
110
PFEM Online Feature Flag @ newmo
shinyaishitobi
2
260
React Server ComponentsでAPI不要の開発体験
polidog
PRO
1
360
Featured
See All Featured
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
251
21k
The World Runs on Bad Software
bkeepers
PRO
70
11k
How to train your dragon (web standard)
notwaldorf
96
6.2k
Fantastic passwords and where to find them - at NoRuKo
philnash
51
3.4k
Why Our Code Smells
bkeepers
PRO
338
57k
Thoughts on Productivity
jonyablonski
69
4.8k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
139
34k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
9
770
Six Lessons from altMBA
skipperchong
28
4k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
31
2.2k
How GitHub (no longer) Works
holman
314
140k
Faster Mobile Websites
deanohume
309
31k
Transcript
tsconfig.jsonの設定を⾒直そう! フロントエンド向け 2024夏 2024-08-06 TSKaigiサブイベント #1 フロントエンド
発表者紹介 uhyo 株式会社カオナビ フロントエンドエキスパート 普段はTypeScriptとかReactをやっている。 好きなTSのコンパイラオプションは noUncheckedIndexedAccess (機能に加えて名前の覚えにくさが好き) 2
tsconfig.json TypeScriptのコンパイラオプション等を記述した ファイル。 tscやエディタ等から参照される。 tsc --initによって作成できる。 Next.js等が勝⼿に⽤意してくれる場合もある。 3
tsconfig.jsonのベストプラクティス TypeScriptの進化に伴ってベストプラクティスも 変化を続けている。 今回はフロントエンド向けの設定を中⼼に紹介。 この機会にtsconfig.jsonを点検しましょう。 4
moduleResolution 5
moduleResolution: “bundler” ⼀番フロントエンドに特有なのはこれ。 バンドラを使っている場合に有効な設定。 古い慣習が残っている場合はアップデートしよう。 “moduleResolution”: “node”, “moduleResolution”: “bundler”, 6
moduleResolutionとは その名のとおり、モジュール解決の⽅法を決める。 importで指定されたモジュールが実際にどのファ イルに当たるかを判定するのがモジュール解決。 import … from “react”; → node_modules/react/index.js
import … from “./foo”; → ./foo.ts 7
moduleResolutionの値 (1) 昔からあった2つ: • classic: node_modulesをサポートしていない。 • node: Node.jsのようにnode_modulesからライブラリ を探す挙動をサポート。のちにnode10という別名が
ついた。 8
moduleResolutionの値 (2) • node16/nodenext: Node.js 16以降でのモジュール解 決の挙動を再現するモード。 具体的にはCJS/ESMの区別、package.jsonのexportsの サポートなど。 ESMをインポートするときは拡張⼦を省略できない仕様も再現されている
import … from “./foo.js”; → ./foo.ts 9
moduleResolutionの値 (3) • bundler: webpackなどのバンドラ挙動を再現する モード。package.jsonのexportsをサポート。 Node.js⽤モードとは異なり、ESMの場合でも 相対パスの拡張⼦を書かなくていい。 拡張⼦を省略してもimportできる! import
… from “./foo”; → ./foo.ts 10
moduleResolution: “bundler” 昔から使っているtsconfig.jsonの場合、 とりあえずnode_modulesを使えるモードとして nodeが指定されていることが多い。 ⾒直してみよう。 “moduleResolution”: “node”, “moduleResolution”: “bundler”,
11
baseUrl 12
baseUrlは消そう baseUrlが設定されている場合、多くの場合は不要 なので消しましょう。 “baseUrl”: “./something”, 消す 13
なぜbaseUrlが設定されているのか 昔のバージョン(4.0以前)でpathsを設定する ためにbaseUrlが必須だった名残で指定されている。 今はもうその必要がない。 14
baseUrl設定の弊害 相対パスではない(./で始まらない)指定なのに baseUrlからの相対パス扱いでimportできてしまう (バンドラと設定が合わず怒られがち) import … from “foo/bar/xxx”; → src/foo/bar/xxx.ts
(baseUrlが./srcの場合) 15
target 16
targetの意味知ってますか? targetにはes5とかes2023とかesnextとか 書くことができる。 これは何を指定しているのか分かりますか? “target”: “es5”, 17
targetの意味 コードの実⾏環境がどのバージョンの機能を サポートしているか指⽰する。 • そのバージョンのJSにトランスパイルする • そのバージョンまでの型定義を読み込む • 正規表現でそのバージョンでは使えない構⽂を弾く 例:
/^foo(?<num>¥d+)/.test(str) ← これはes2018未満ではコンパイルエラー 18
targetの注意点 • そのバージョンのJSにトランスパイルする SWCなど別のツールを使っている場合はtargetを⾒ないことも • そのバージョンまでの型定義を読み込む libを別に指定している場合はそちらが優先される • 正規表現でそのバージョンでは使えない構⽂を弾く これはTS
5.5から 19
targetの設定指針 基本的にはコンパイラオプションの意味に忠実に。 動作環境を表す値を設定すべし。 libを別に指定している場合はlibもメンテしよう。 libやtargetがメンテされていないせいで最近の 機能を使えていないコードベースは悲しい。 (配列のflatMapとか) 20
module 21
moduleオプションとは コードがどんなモジュールシステムで動くのかを 指⽰するオプション。 targetからモジュールシステムだけ抜き出して 別のオプションにしたと思えば⼤体合ってる。 (targetはESバージョンに着⽬した指定だが、モジュール システムは環境によって異なることを反映したオプション) 22
moduleオプションの値 歴史的経緯を反映して指定可能な値が⾊々ある。 commonjs es2015 es2020 es2022 esnext amd system umd
node16 nodenext preserve 23
TypeScriptのモジュールシステム (1) TSにおけるimport/exportは、常にES Modules のセマンティクスに従うもの。 moduleをcommonjsにした場合、トランスパイル時に CommonJSに変換される。 import { foo
} from "./foo"; console.log(foo); const foo_1 = require("./foo"); console.log(foo_1.foo); 24
TypeScriptのモジュールシステム (2) ES Modulesとは無関係にただ単にCommonJSの 構⽂へトランスパイルしてほしい時のための TypeScript独⾃構⽂も⽤意されている。 import foo = require("./foo“);
console.log(foo); const foo = require("./foo"); console.log(foo); 25
TypeScriptのモジュールシステム (3) module: “esnext” が設定されている場合、 トランスパイル先がCommonJSに対応していない純粋な ES Modules環境だと解釈されるので、 独⾃構⽂は使⽤不可となる。 import
foo = require("./foo“); console.log(foo); ✖ 26
moduleオプションの指定 “moduleResolution”: “bundler” と組み合わせる 前提だと、moduleの指定は2択。 • “module”: “esnext” • “module”:
“preserve” 27
moduleオプションとバンドラの関係 (1) 今どきのバンドラはES Modulesを解するので、 ES Modulesのみの環境を表すesnextが適切と 考えられていた。 しかし、webpackなどrequireを解するバンドラ もある。また、Bunもimportとrequireを 両⽅サポートしている。
28
moduleオプションとバンドラの関係 (2) これらはimportとrequireを同じファイルで 混ぜられるなど、Node.jsとも異なる 独⾃のモジュール環境であるため、 “module”: “preserve” が与えられた。 29
moduleオプション余談 (1) “module”: “preserve” は、tsconfigが無い 状態でVS Codeが使うデフォルト設定として 導⼊されたという側⾯もある。 旧設定 “module”:
“esnext”, “moduleResolution”: “node” 新設定 “module”: “preserve”, “moduleResolution”: “bundler” 参考: https://github.com/microsoft/TypeScript/pull/56785 30
moduleオプション余談 (2) 旧設定がpackage.jsonのexportsに対応していない といった問題を解消しつつ、Node.js以外の 多様な環境でTSが使われる現状を反映した、 ⾃由度の⾼いデフォルト設定となっている。 旧設定 “module”: “esnext”, “moduleResolution”:
“node” 新設定 “module”: “preserve”, “moduleResolution”: “bundler” 31
tsconfig.json⾒直しポイントまとめ “target”: “es2023”, ← ちゃんとバージョン上げる “module”: “esnext”, ← もしくはpreserve “moduleResolution”:
“bundler”, ← nodeから変える // “baseUrl”: “./…”, ← 残ってたら消す ※ バンドラを⽤いるフロントエンド向けの設定です 32
おまけ―モジュール周りの Node.jsの動きについて 注意: 以降の説明は現状のexperimentalな実装のものであり、 リリースされるまでに内容が変化する可能性があります 33
Node.jsのESMではimportに拡張⼦が必須 “moduleResolution”: “node16”の場合、相対パスでの importは拡張⼦が必須。 また、実際のファイルが.tsでも、 import宣⾔は.jsで書く必要がある。 import { foo }
from “./foo”; → コンパイルエラー発⽣ import { foo } from “./foo.js”; → ./foo.tsに解決される 34
Node.jsのESMではimportに拡張⼦が必須 これは以下の理由で説明される。 • .tsファイルはコンパイル後に.jsファイルになる。 • TSは勝⼿にimport元を書き換えることをしたくないので、 あらかじめコンパイル後の拡張⼦で書く必要がある。 import { foo
} from “./foo”; → コンパイルエラー発⽣ import { foo } from “./foo.js”; → ./foo.tsに解決される 35
ところが…… 最近、Node.jsは.tsファイルを直接実⾏できる機能の 導⼊を検討している。(--experimental-strip-types) とりあえず初期実装は⼊った。 .tsファイルが与えられた場合SWCを使って JSにトランスパイルしてから実⾏する。 参考: https://github.com/nodejs/node/pull/53725 36
Node.jsのTS対応とモジュール解決 なんと、Node.jsのTS対応を利⽤する場合は .tsでimportする必要がある。 既存のNode.js向けTSコードとの互換性を重視せず、 新機能に合わせたコードを書いてもらう設計。 import { foo } from
“./foo.js”; → MODULE NOT FOUND!! import { foo } from “./foo.ts”; → OK (loaderでのモジュール解決がつらくなるのを避けるためという理由が主らしい) 37
Node.jsのTS対応とモジュール解決 デフォルトのTSの設定では.tsをimportすることは 禁⽌されている。 allowImportingTsExtensionsを有効にすれば可能 だが、noEmitも⼀緒に有効にする必要がある。 (事前のトランスパイルが不要でランタイム/バンドラが 直接.tsを解釈できるなら許すという考え⽅) 38
Node.jsのTS対応まとめ 従来のやり⽅(事前にTS→JSトランスパイルする)と 新オプションのやり⽅(Node.jsで直接.tsを実⾏できる) ではimport宣⾔の書き⽅が異なるので、 どちらかを選ぶ必要がある。 コミュニティの分断が⼼配。 39