TSKaigi2025に行ってきました
昨年に引き続き、TSKaigi2025に参加してきました!
今年はベルサール神田で2日開催ということで、現地で2日とも参加してきました。
とにかく気になるセッションだらけで、朝から夕方までずーーーっといろんな話を聞きまくってました。
(おかげで腰と背中が爆発寸前ですww)
せっかく良い知見をたくさん得られたので、つらつらとアウトプットを書こうと思い、今回の記事を執筆しました。
注意事項
- この記事は個人の見解となります
- あくまで私が感じたこと、解釈したことがベースとなっているため、本来の解釈の意図とは異なる内容が書かれている可能性があります
- ピックアップについては、私が実際にセッションを直接聞いて気になったものとなります
ピックアップ(1日目)
checker.tsに対して真剣に向き合う
- TypeScriptのコンパイラとして動いているchecker.tsの話
- 5万行くらいあるけど、実際の中身ってどういうことやっているの?をLLMを使って解析していた
- LLMに解析させて概要をまとめさせたり、グラフとして図式化することによって、ぱっと見で何をやっているかを直感的に掴むことができそう
- checker.tsに限らず、一見何をやっているかがわかりづらいライブラリ・コードに関しても、LLMに食わせればある程度理解ができるかも、という知見を得た
(※資料上れば後ほど添付)
TypeScriptで実践するクリーンアーキテクチャ ― WebからもCLIからも使えるアプリ設計(⭐️)
- ここまで出すか?ってくらいBobおじさんの写真が出てきた
- クリーンアーキテクチャを実際にTS,Next.js(アプリ)に落とし込んでやってみようという話
- 今回はスクラムチームの管理
- SOLID原則のD,依存関係逆転の原則(DIP)が一番重要としている
- ここの図、めっちゃわかりやすかった
- 非依存なソフトウェア設計をする上で重要な考え方
- アプリでは「web,cli」 +「package」という構成
- web,cli: 入出力層
- package: ドメイン層、ユースケース層、ゲートウェイ層
- ユースケース層はドメイン層にのみ依存
- ゲートウェイ層は外部システムとの連携、およびドメイン層のインターフェースを実装する場所
- クリーンアーキテクチャ、もう一度読み直そうと思わされたセッションだった
堅牢なデザインシステムをつくるためのTypeScript活用
- 「デザインシステム = ルールセット+ドキュメント+実装」
- 型の制約を利用してデザインシステムを強制していく
- デザイントークンの型制約
- style dictionaryを利用し、Propsの自動生成
- Branded Typesにより、Spacing,Radiusのような構造が同一なものを区別する
- ポイント:styleをPropsで管理する
- classNameやstylesは受け取らないようにする
- css Variablesをテンプレートリテラルで管理する
- JS Docでduplicatedなpropに斜線が引ける
- アップデートを知らせることができる
- ubie-uiいいね
- (うちのプロダクトもこのくらい整えたいなと感じた)
- figmaとの連携
- figmaとgithubActionsとの連携 rest-api-spec
- LLMによるドキュメントの更新
- LLM支援を最大化したいなら、モノレポが効果的
AWS LambdaをTypeScriptで動かして分かった、Node.jsのTypeScriptサポートの利点と課題
- デプロイ時のトランスパイルが不要
- ts-nodeやwebpackなども不要
- type strippingがついた
- ただし、型定義にはtypeを使う必要がある
- enumやnamespaceなどはサポートされない
- 型チェックが事前に動かないので、事前にtscなどでチェックする必要がある
- サーバーレス環境では引き続きトランスパイルは必要
- ローカル環境で試しに使いたい、となった時に使えそう
fast-checkとneverthrowのPBT+Result型で堅牢なビジネスロジックを実現する
- ビジネスロジックを記述する方法
- try-catchの例外処理の受け取りが型安全ではない
- Unionを使う
- Result型
- neverthow
- fp-ts
- プロパティベーステスト
- fast-check: ランダムに条件に沿った値を生成することができる
ピックアップ(2日目)
TypeScriptネイティブ移植観察レポート TSKaigi 2025
- なぜGoが選ばれたのか
- 約9ヶ月で25万行のうち、15万行が移植された
- 2025年中に完了予定
- ネイティブ✖️並列処理で10倍
- ネイティブ
- 文字列:jsはutf-16、goはutf-8
- 並列処理
- 型チェッカーで一旦4分割固定の並列処理している
- 将来的にはoptionalで変えられるかも..?
- 互換性の話
- Unionや型自体の決定的順序付け
- 並列化によって順序が変わってしまう
ー Strada(tsプロジェクト)の人が, 「Project Corsa」にも関わっている
- 一部はGoで使われていない、自動変換で一部は手動で修正
- AIは使っていない
- ランダム要素が多く、決定的な移植(既存に合わせる)に向いていない
- レビュー等で使っている
- ts,tsx以外の言語プラグインに影響が出そう
- vueやangularなど
- ts-morphはownerが追従の余力がないと言ってるらしく、今後注意しなくてはならない
複雑なフォームを継続的に開発していくための技術選定・設計・実装(⭐️)
- 難しいフォーム実装に設計と技術選定で向き合う
- フォームライブラリ(useForm)+バリデーションライブラリ(zod)の組み合わせで、構造と制約を宣言的に書ける
- フォーム実装自体が難しいもの
- useFieldArray,useWatch
- watchやsetStateの数が増えてくると限界が見えてくる
- zodで表現できるのは、制約と形状
- フォームにおけるモデルをUIから分離(関心の分離)
- zodの中に実は重要なロジックが埋まってる、なんてことも
- テストも書きやすい
- 複雑かつ非同期な場合でも、jotaiのようなライブラリだとシンプルに扱える
- コアな部分はReactに依存していない
- 同じようなライブラリはいくつかあるので、プロダクトの特性などに基づいて選定する
バランスを見極めよう!実装の意味を明示するための型定義
- optionalと
| undefined
は場面によって使い分ける- 例えばプロパティが足りないから型エラー出してほしい、というときは
| undefined
で
- 例えばプロパティが足りないから型エラー出してほしい、というときは
- Unionの評価の網羅性とneverの組み合わせでエラーハンドリングをする
- 全ての型に対する処理を行っていれば、最後にはneverだけが残る
- 型注釈はプロセスの外部で管理したり、複数から参照する場合などは付けたほうが良い
技術書をソフトウェア開発する - jsprimerの10年から学ぶ継続的メンテナンスの技術
- jsprimerとjser.infoの人だ!と感動
- TSから型を破るとJSになるので話します、は確かにとなった笑
- JS周りのエコシステムは変化し続けるので、技術書の内容はすぐに古くなる。メンテナンスが継続的に必要
- 読みやすいように定期的にスナップショットとして書籍を出している
- jsprimerでは常に最新版を保っている
- jsprimerでは、書くより読む回数が多い
- 更新を継続的に行うのに、何度も読む
- 読みやすいかどうかを重視する
- 既知の情報を使って未知の情報を表現したり伝える
- 以下はソフトウェア開発にも通ずる(一部)
- 依存関係を最小化にする
- 目的と範囲の明確化
- 真面目に技術書を書くのと、真面目にソフトウェア開発するのは同じ
機能的凝集の概念を用いて複数ロール、類似の機能を多く含むシステムのフロントエンドのコンポーネントを適切に分割する(⭐️)
- どのくらいの粒度でコンポーネント分けてますか
- ドメイン・要件(今日はここがメイン)
- UI
- その他
- 論理的凝集
- 似たような処理をフラグ・条件でUIを切り替える
- コンポーネント内に条件分岐が増える、可読性が落ちがち
- 細部に場合分けの多い文章は読みにくいはず
- 機能的凝集(こっちが良いのでは)
- 単一の目的のために構成されている
- コンポーネントの責務が明確になる
- 共通化したい余地が残る
- 意味的な部分を切り出せば良い
- 機能修正や追加に耐えやすい
- 要件とコードが一致しているかを確認しやすい
- 共通化したいなというエンジニア的な嗅覚直感はあるが、いろんな要素から総合的に判断したい
TS特化Clineプログラミング(⭐️)
- 言語特化プロンプトは必要
- 言語ごとのユースケースに最適化されてない
- プロンプトは書きすぎない
- 長すぎると途中で破綻する可能性がある
- 効くプロンプト
- テスト駆動
- コメントを書く
- unit-testを書く
- types.tsにドメイン型を集約
- 関数型ドメインモデリング(classを使わない)
- ファイルの配置規則を明記
- 詳細指示はdocs/*.mdに分割しておいておく
- TIPS: typescript.d.tsをpin留めしておくとCopilotが優先的に見てくれて、コード補完がうまくいきがち
- うまくいかない例
- 非同期処理のtry-catchが下手
- 環境構築から任せる(ゼロショット)
最後に
どのセッションもかなり興味深かった反面、私が聞いたことのない考え方、ライブラリ、技術もいっぱい出てきて、まだまだインプット不足だなと感じた時間となりました。
また2日ともめちゃくちゃ美味しいお弁当(特に2日目の牛タン弁当は最高でした)を配っていただいたりとか、2日目には階段移動も可能としていただいたり、参加者が精一杯楽しめるように運営の方に動いていただいているんだなと実感しました!
来年もぜひぜひ参加したいと思います!
ありがとうございました!