🤖

TSKaigi2025個人的参加レポート/メモ

に公開

はじめに

今回、TSKaigiに初めて参加しました。TS自体は2020年頃から
実務で必要になった経緯で始めて今も継続的にTSを使用している筆者です。
話題の?ts-goの話やFP、JSPrimer、Coding Agent x TSと言った有名どころの
セッションをメインで聴講させていただきまして、大変学びが多かったです。
登壇された方々、運営の皆様ありがとうございました。
Tシャツ含め色々と配布物やスタンプラリーもあり、そちらも含めて楽しかったです!

総合的な感想

真面目な話を書くと、まだたくさんソフトウェア開発には面白いところがあるなと思った次第です。
FPの話ではもっとOOPのデザインパターン含めて学べることがありますし、FPだけで取っても
うまく思想を学べていなかったなと振り返ることができるセッションでした。
また、neverthrow・Result型に関する話題が複数ありまして、TSを書いていると辛くなる例外処理の解が一定出揃い始めている感がありました。結論、Result型(error as values, goのあの書き方ですね)が後続の処理に信頼性の高い状態で続けることができ、保守もしやすいよね、と言うふうに捉えました。
neverthrowに関してはTSKaigi後に少し使ってみたのですが、Rustライクな記法であまりTSっぽくない印象を受けており、TSを長らくやってきた筆者としてResult型を学ぶのには良いが、中々辛い書き心地だと思っています。もっと良いライブラリ出ないですかね。Result型をTSライクな記法でできるやつとか。(自作してみますか?余裕あればチャレンジしたいところです)

メモ及び個人的な所感

TypeScriptネイティブ移植観察レポート TSKaigi 2025

TSのコンパイラ部分をgoで移植する、と言った一世を風靡した?話題についてです。
どこかで色々語られていることを集約した内容とのことでしたが
かなり深く観察されていて、数記事読んだことのある身でも学びがありました。
特に筆者はGoを業務上使う人なので、error as valuesで早期にエラーを返す
鬼みたいなコードに何も思わないよねと言ったお話のところでクスッと笑ってしまった記憶があります笑

資料:https://speakerdeck.com/berlysia/typescript-native-porting-observation-tskaigi-2025

呼称

Strada: 従来の実装

  • イタリア語の道
    Corsa: Goの実装
  • レースモード、早い

移植理由

  • 大規模PJTでのoomの頻発
  • 柔軟なオブジェクトモデルがコンパイラに向いてない

なぜ"移植"なのか

  • TSの挙動はどこかで使われている
    • バイラムの法則:利用者が十分いるとき、仕様ではなく観測可能な振る舞いに誰かが依存する
  • 型チェッカーに後方互換性は必須

なぜGoか

  • 実装スタイルが似ている
  • GCかつ循環参照を自然に使える(TSのASTも循環参照)
  • 共有メモリの並列処理
  • クロスプラットフォーム

10x Fasterの内訳

ネイティブ化(3x~3.5x)x 並列処理(3x~3.5x)= 10x

ネイティブ化

  • JIT、柔軟で動的なオブジェクトモデルから脱却
    • 予測可能でチューニングしやすい
  • メモリの効率化
    • JSはオブジェクトだと全部ヒープに入る→断片化する
    • Corsaの実装でまとめて格納+不足時に割り当てる
  • 文字列管理
    • JS: UTF-16, Go: UTF-8、バイトが半分
    • go slice: メモリアロケーションなしでスライスを取れる

並列処理

  • ファイル毎に並列化
  • 型チェッカーPJT→4分割して並列化
    • 出てくるエラーの順番が変わったりするから、4分割にとどめている

互換性

  • 99.99%の目標
  • 10万件のエラー差分検知テスト
  • とはいえ、変更点もある
    • Union、型の決定順序付→並びが変わる(今までは実装順序通りの固定で安定しない)

開発スピードの背景

  • Stradaの開発者がCorsaにも関与
    • 移植専門ではない
  • TS→Goの構文変換ツールを利用
    • 自動変換→細かい違いを人がなおす、テストで検証のサイクル
  • AIベースの一括変換を使っていない

パフォーマンスバジェットの使い道

  • 方の決定的な順序付→旧実装から7%+
    • これまで見送った改善を進められるかも
  • induced demand: できた余裕を使い切らないようにバランスを取る

Pragmatic Functional Programming in TypeScript

yasaichiさん

このセッションを聴いて、より関数型の思想や手法を学び
既存のアーキテクチャに適応させていきたいと感じさせる内容でした。
関数型とは何ぞや、といった概要説明からある原則を使って、実務でどう適用していったのか
そのストーリーが楽しいものでした。

資料:https://decks.yasaichi.com/20250524/pragmatic-functional-programming-in-typescript

理論と実務のギャップ

例:カリー化とHOC

  • プログラムの見た目が違いすぎる→導入に見合う成果が出るか
  • バックエンドの場合、クラスベースのOOPが主流で組み込み可能か

ギャップを埋める5原則

Dmitrii Kovanikovさんのジョークポスト

  • Pragmatic
  • 小さく初めて早期に効果検証できる
  • 標語形式で覚えやすい

原則

  1. Parse, don’t validate
    • bool, voidではなく検証済み専用型で結果を返す(最近のライブラリではそうなっている)
    • 「検証済み専用型で結果を返す」→事後条件と関連
    • 信頼性と保守性の向上
    • 例:プロパティのカプセル化がなくなる
  2. Make illegal states unrepresentable
    • 型システムを使って不正なデータや状態を表現できなくする
    • 不変表明
    • 信頼性と保守性の向上
    • 例:
  3. Errors as values
    • 例外をスローではなく、値として返す
    • 事後条件(失敗した場合に検証する必要性を示す)
  4. Functional core, imperative shell(アーキテクチャの話)
  5. Smart constructor
    • ある型の値で、制約を満たした場合にのみ生成可能にする
    • 不変表明
      • 後続処理の設計を改善する
    • 賢いstatic生成メソッド

結局は型を見ていて、4原則の不変表明、事後条件を表現する。

ワード
不変表明:常にある型のみを持つデータ構造である

アーキテクチャ

Effect(zod, neverthrowとかがオールインワン)

戦術的DDD

  • Value Object: brand型
  • Entity: brand型のプロパティ, 型レベルでメソッドが使える、使えないがある
  • service, repository: Error as Values
  • presentation: エラーのパターンマッチング→HTTPのエラーに変換
  1. Functional core, imperative shell
    • 純粋関数のコアと副作用シェル

controller以外:不変表明・事後条件
controller:型で表現された異常系に対処、処理を実行
all:副作用の処理を分類

5原則はFPに限らず、クラスベースでも活用可能。

技術書をソフトウェア開発する - jsprimerの10年から学ぶ継続的メンテナンスの技術

JSPrimerの開発者、azuさんによるセッションです。
技術書とはこうある方が良いよねと言った話からソフトウェア開発としての
あるべき姿(*1) を考えさせられる内容でした。
OSS x お金の部分もかなり勉強になりました。
ソフトウェアエンジニア必携の内容だったように思います。

*1: 筆者はスクラムガイドなどで見るハイパフォーマー層をイメージ

資料:https://efcl.info/2025/05/24/tskaigi-2025-jsprimer/

  1. 変化を前提とした設計

    • 目的外を明確にして、依存を減らす
  2. 読みやすさを優先する

    • 書きやすさ<<読みやすさ
    • 継続的に更新する→何度も読む
      • 読む回数が多い
    • →読むコストを下げる(構成、表現統一...)
      • 工夫例:既知の言葉→未知の内容(known new contract)
  3. テスト

    • docsの自動テスト
      • textlint: 自然言語のESLint(表現を統一しやすくする→描きやすくなる)
      • power-doc-test: ドキュメント内のコードをテストする
      • Docsの依存、参照をチェック
    • CI/CD
    • 読みやすさ分析(独自ツール)
  4. 変化に追従する

    • 大きな変更 → Design Docを書く
  5. OSS開発

目的:変化に対応できるようにする
OpenCollectiveの面白いところ:ポイントに応じて、貢献者に年間予算から支払う
アウトカム設計

  • 変化に強い設計思想の採用
    • 依存関係の最小化
    • 構成の見直しと再構築
    • 目的と範囲の明確化
  • FBサイクル
    • ユーザ
    • 定期更新
    • メトリクスによる改善点の可視化
    • コミュニティベースの運営モデル

真面目な技術書とソフトウェア開発は同じ

TS特化Clineプログラミング

mizchiさんによる圧倒的なまでのAgent Codingの実体験トークでした。
実際に我々が活用していてうんうん、わかる!と言った所謂”あるある”から
多くの人が言語化できていないプロンプトテクニックまで
学びが多かったセッションです。
Coding Agentの活用方法を模索している全エンジニアが聴いた方が良いと思いました。
筆者は聴いて考えて納得して、これはこう活用できそう、応用できそうを繰り返し
酸素不足になりました()

資料:https://zenn.dev/mizchi/articles/typescript-for-cline

ゲームチェンジャー

  • 2014: 仮想DOM
  • 2025: CLINE

うまくいくプロンプト

言語特化プロンプトが必要

  • Coding Agentは特定のユースケースに最適化されていない
  • 言語間転移学習が不安定

プロンプトを書くコツ

  • 書きすぎない(再現性のある範囲で詠唱破棄)
    • TDDならTDDだけで良い
  • 執拗に出力令を支持する
    • ゼロショットの夢はない
  • 両立条件の矛盾を避ける
  • 段階的に厳しい内容に取り組ませる

効くプロンプト

  • TDD(最重要)
    • インテグレーションとかいくと、壊れ続ける
    • そこで評価が必要だが、自律的な修復能力
    • 高品質なテストがあれば一瞬で完成する
  • コメントによる自己記述
    • 別のタスクでも再現性を持ってコードを書かせるため
    • 2回目以降もいける
  • In Source Testing
    • コメント/実装/テストは三位一体
      • それぞれがそれぞれを補強させる
    • 欠点:ファイルが肥大化しやすい(800~1000行あたりが限界)
  • types.tsにドメイン型を集約
    • single source of truth(SSoT)
    • 型は実装と比較して変更頻度が低い
    • 2000行くらいでも比較的なんとかなる
  • TS + 関数型ドメインモデリング
    • classだと内部状態が増える→状態の推論が人間でもAIでもしんどい
      • private memberが同時に複数書き換わるとか、、、
    • throwも避ける
  • ファイル配置規則を明記
    • ないと、構造を分析+推測し始めるのをスキップできる=立ち上がりのスピードが違う
  • 詳細指示をdocs/**.mdに分割
    • 書きすぎると、味が薄くなる→全無視してしまう
      • 人もAIも最初と最後しか見てない
    • 分割後、適切に与えるようにする
    • 大規模用(3000行~, 中規模は1500くらい)
  • Copilot TIPS: 型定義ファイルを一時的にピン留め
    • VSCodeの設定で
  • Copilot TIPS: コメントから書き始める
    • インラインプロンプトだと思う
    • 型定義ファイルを一時的にピン留め、と相性が良い
    • 最終的によく消す
  • カバレッジに基づくテストの自動生成
    • metaの論文
    • 4割の打率で生成できる
    • カバレッジの仕組みあれば採用して良い
  • 機械的なマイグレーション
    • ライブラリとか
    • 読んでやれ、を繰り返すだけでOK
    • 最後は人力
  • 似たAPIのライブラリに置換する
    • API、概念が類似しているもの
    • マイグレーションガイドを置いてからやらせるとOK
  • URLを読ませるMCP(自作)
    • 人が検索したものを与えて、やらせる
    • npm-summary

うまくいかないプロンプト、その分析

  • 型だけで設計
    • 型から実装もテストも全部やってもらう
    • TSにTypeだけで抽象的に実装するトレーニングデータがない→厳しそう
  • 非同期の例外処理が下手くそ
    • 思考停止気味にtry-catchしてエラーを握りつぶす
  • 環境ゼロの環境構築が下手
    • 環境そのものが一番強力なプロンプト、ゼロショットは発散
    • やばいことを繰り返してリカバリできない範囲まで破壊する(注意)
    • Vibeしたければ、ボイラーテンプレートが必要
  • モジュールインターフェースが発散
    • 実装全部をエクスポートする(消さない)
    • モジュール間の契約が肥大化して破綻
  • あるのがよくない!
    • チェーホフの銃の法則:LLMプロンプトエンジニアリング
    • 無関係なリソースを読み込んでも、それを使うことに固執する
  • デバッグログの食い過ぎ
    • 実装→デバッグを埋め込む→ターミナル出力を膨大にする→コンテキストウィンドウが死ぬ
    • Claude系はログを片付けない(注意

結論:やっぱりLLMはコーディングが下手

  • 低品質コードで設計破綻
    • リファクタ指針がない
    • デッドコードを不要と思ない
    • モジュール視点でAPI設計できない
  • ユーザーのリファクタを元の低品質コードに直してくる

TS+LLM

  • python, tsの学習量が多い
  • 安全性よりも表現力な型システム(ドメイン表現できるが、安全ではない)→表現が豊富
  • 静的解析手段が多く、誰かがやってる

TSの課題

  • 例外機構が貧弱
  • デフォルトミュータブルでreadonlyが使いづらい
    • AIも実はこれ書き換わるんじゃないかと思ってしまう

Lintルールのバイブコーディングは向いている

まとめ

  • TDD:人間がAIの作業に入らなくて良いようにする
  • 必要
    • LLMの得意領域/発達段階を予測する
    • プロンプトエンジニアリング
  • 変わってない
    • プログラムの最終的な難易度、複雑性

Do

  • AIに得意なことをやらせる
    • VLMのコストを見る
  • コード生成にスキルを寄せる
  • 自動テスト+プロンプろ
    • Prompt Engineering Guide
    • オライリーのやつ

Discussion