メドピア開発者ブログ

集合知により医療を再発明しようと邁進しているヘルステックカンパニーのエンジニアブログです。読者に有用な情報発信ができるよう心がけたいので応援のほどよろしくお願いします。

メドピアは TSKaigi 2026 にシルバースポンサーとして協賛しました 〜印象に残ったセッションを紹介します〜

こんにちは。エンジニアリング推進室の小林和弘(@kzhrk0430)です。

2026 年 5 月 22 日(金)〜 23 日(土)の 2 日間にわたって開催された TSKaigi 2026 にメドピア株式会社はシルバースポンサーとして協賛しました。私自身も個人スポンサーとして協賛させていただき、当日現地にお邪魔させてもらったので印象に残ったセッションや現地の様子をいくつかご紹介させていただきます。

会場入口に展示されたスポンサーロゴを指さしている四人の男性

今年は会場をベルサール羽田空港に移しての 2 日間開催で、TypeScript をテーマにした国内最大級のカンファレンスとして、今年も大変盛況でした。

TypeScript の言語処理系そのものの話から AI 時代の型設計の話まで幅広く聞けたのはとても良い刺激になりました。今回はその中でも個人的に印象に残ったセッションをいくつかピックアップして紹介したいと思います。

業務に残された「よくない型」で考える「TypeScriptの難しさ」(Saji)

speakerdeck.com

まず最初に紹介したいのが、Saji さんによる「業務に残された『良くない型』で考える『TypeScript の難しさ』」です。

「成功にパターンはないが失敗にはパターンがある」という格言から始まり、実際のプロダクトのコードベースに残ってしまった anyas@ts-ignore といった「良くない型」を収集・分類(パターン化)することで、TypeScript の難しさの一端に迫っていく、という構成のトークでした。

冒頭で「これは『こんな型を書くなんてダメ!』というトークではありません」と強調されていたのが個人的にとても好印象でした。誰だって好んで as@ts-ignore を書いているわけではなく、自分だって多少はやったことがあるはずで、その上で「なぜそうなってしまうのか」をパターンとして捉え直そう、という姿勢です。

3 つのパターンに分類する

最初のパターンは 動的な境界での型落ち です。DOM イベントや catch (e) のような、どうしても型が広くなってしまう箇所の話です。e.target as HTMLButtonElement(e as Error).message のような as がここに該当します。これらは currentTarget を使ったり instanceof で narrow したり型ガード関数を共通化することで、ある程度安全側に倒せるという話でした。

次のパターンは 動的な配列・Object 変換 です。Array.prototype.includesreadonly な配列だとリテラル型を要求してしまう問題や、Object.fromEntries / Object.keys の戻り値が構造的部分型の限界で劣化してしまう問題など、標準メソッド単体ではどうしても解決が難しいケースです。これらは自作のヘルパーや型ガードを書くことで、ある程度効率的に安全側へ寄せられる一方、narrowing や型ガードはユーザー次第な部分が大きいので慎重に、というまとめでした。

最後は Union の扱いの難しさ です。本来 Discriminated Union にできるはずの型を、typevalue を別々の式で組み立ててしまって直積型になってしまう例や、引数の Union から戻り値を推論しづらい例、ジェネリックな引数でハンドラを呼ぶ例などが紹介されていました。データ生成において Discriminated Union にできないのは設計の問題で、対応させたい型は常に一緒に生成することを忘れない、という指摘が特に印象に残りました。

「押し戻せるか」という分類軸

個人的に一番なるほどと思ったのが、これらのパターンを「外部との境界由来か、内部由来か」「安全圏に押し戻せるか、押し戻せないか」という 2 つの軸の 4 象限で整理していたところです。

境界由来で押し戻せるものはスキーマ(Zod 等)を含む型ガードで対応し、「型ガードを書ける場所では書く」をチーム規約にする。内部起因で押し戻せるものはチームで型ヘルパー・型ガード集を持つ。そして内部起因で押し戻せないものは、ある程度諦めて局所的に as@ts-expect-error を理由コメント付きで使い、TypeScript の進化(e.g. 5.5 導入された Array.prototype.filter の型推論改善)を追っていく。こういった対策が分類ごとに整理されていました。

このセッションを通して感じたのは、これは「TypeScript の難しさ」というよりは「TypeScript の型システムが完璧ではない」という話なのではないかということです。業務で書かれてしまう「良くない型」には、TypeScript の不完全さによって生まれてしまったケースと、実装の歪みによって生まれてしまったケースの両方がありそうで、これは発表での「境界由来 / 内部由来」という分類軸ともよく重なります。

そして個人的に得た気付きとして、TypeScript の「良くない型」はレガシーコードやアンチパターンの検知につながるのではないか、という視点があります。「良くない型」が集まっている箇所は、TypeScript の限界というより実装の歪みが出ている箇所である可能性が高く、そこを起点にコードの危ういゾーンを炙り出していけるのではないか、と考えています。

プラグインで拡張されるContextをtype-safeにする難しさと設計判断(kazupon)

speakerdeck.com

次に紹介するのは、kazupon さんによる「プラグインで拡張される Context を type-safe にする難しさと設計判断」です。

kazupon さんといえば Vue.js 日本ユーザーグループの代表で、Vue Fes Japan のオーガナイザーでもあり、弊社の Vue Fes Japan 2023 After Meetup にも特別ゲストとしてお越しいただいた方です。今回は JavaScript の CLI 開発ライブラリ「Gunshi」の v0.27.0 でリリースされたプラグイン機能を題材に、プラグインによって動的に拡張される Context をどうやって type-safe にするか、という型設計のお話でした。

Gunshi にプラグインという機能拡張を入れるにあたって、現在の型の状況・プラグインという機能に求められる型の条件・複数の型設計の検討という流れで話が進んでいき、型を使って Gunshi の開発者・利用者・プラグイン開発者の体験をよくするために何が最適なのかを、どう考え抜いたのかが詳細に語られていました。TypeScript の型システムを最大限活用していることがよく伝わってくるセッションでした。

値が作られるタイミングと、型が必要なタイミングがずれる

Gunshi では、コマンドを定義する define() を起点に CommandContext の型が決まり、run(ctx) まで型が伝播していく仕組みになっています。ここにプラグインが加わると ctx.extensions に値やロジックが動的に追加されます。

ctx.extensions の中身は CLI を起動してプラグインを適用した後に作られるのに対し、プラグインの型はコマンドを定義する define() 実行時に必要になる、というタイミングのずれが発生します。つまり、実行時に注入された値を定義時に型として参照する必要があります。この課題を解くために、プラグイン ID・プラグイン同士の依存・コマンド側が期待する extension という 3 つを型でつなぐ必要がある、という整理が非常に明快でした。

4 つの設計アプローチとトレードオフ

発表では、この問題を解くための設計アプローチとして、Module Augmentation・Fluent Interface・Explicit Context Type・Compositional Type Augmentation の 4 つが比較されていました(名称の一部は kazupon さんによる命名とのことです)。

Gunshi では Explicit Context Type をベースに採用し、プラグイン ID と Extension 型のペアを Map として表現する設計を選んだ、という結論でした。「宣言ベースのインターフェース」「コマンドモジュールとプラグインが別々の場所に存在する」という Gunshi の特性に合わせた判断だそうです。プラグイン作者にプラグイン ID と Extension 型の責務を持たせているのも面白いです。

応用できる知見

このセッションが良かったのは、最後に提示された「応用できる知見」が、Gunshi に閉じない普遍的な話に着地していたところです。Context のような動的に値を追加できる構造を設計するときは、「追加された値の由来を API に残すか」「型を global に広げるか scope を限定するか」「自動推論を優先するか明示的な契約を優先するか」といった観点で判断することになる、という整理でした。

動的な拡張を type-safe にする設計では、型の表現だけでなく、境界と責務の置き方が重要になるということを学びました。普段ライブラリの利用者側にいることが多い自分としては、こうした設計判断の裏側を覗けたのはとても貴重で、Vue の Composable やプラグイン的な仕組みを設計するときにも効いてくる視点だと感じました。

TS 7: How We Got There(Jake Bailey)

jakebailey.dev

続いては、Microsoft の Jake Bailey さんによる基調講演「TS 7: How We Got There」です。

ご存知の方も多いと思いますが、TypeScript チームは Go 実装のコンパイラである tsgo の開発を進めています。このセッションでは、なぜ Go へ移植するのか、その過程をどう支えたのか、そしてどのように世に出していくのか、といった話が語られていました。

なぜ Go が採用されたのか

このセッションで一番細かく語られていたのが、TypeScript 7.0 でなぜ Go が採用されたのか、という点でした。聞いていて自分なりに整理すると、理由は大きく次の 4 点に集約されると感じました。

  • TypeScript と Go は言語としての構造が似ているということ
  • ガベージコレクションを備えていること
  • async/await のような関数の色分けなしに並列処理を素直に扱えること
  • 学習容易性

聞いていて印象的だったのは、これらが単なる実行速度の話に留まっていなかったことです。移植のしやすさや、チームがその言語にどれだけ早く慣れて開発を進められるか、といった現実的な観点まで含めて検討されていることが伝わってきて、言語選定というものの考え方として勉強になりました。

TypeScript 6.0 の立ち位置と破壊的変更

Go への移植の話とあわせて、TypeScript 6.0 の立ち位置についても触れられていました。聞いた限りでは、6.0 は次のメジャーバージョンへの橋渡しとなるリリースで、いきなり大きく切り替わるのではなく、段階的に移行できるように位置づけられているという印象を受けました。破壊的変更を一度に押し付けるのではなく、移行の道筋を用意してくれているあたりに、このプロジェクトの進め方の丁寧さを感じました。

型チェックのデモが分かりやすかった

個人的に一番おもしろかったのが、型チェックのデモでした。CPU のコアと、その利用率を従来の tsc と新しい tsgo で並べて見せてくれたのですが、これがとても分かりやすかったです。

tsc のときは一部のコアしか働いていないのに対し、tsgo では複数のコアがしっかり使われている様子が目で見て取れて、なぜ型チェックが速くなったのかが直感的に理解できました。数字で「速くなった」と説明されるよりも、リソースの使われ方の違いを視覚的に示してもらえたことで、腑に落ちる感覚がありました。

いつテストを書くか?―ソフトウェア開発における安心と不安について考える(lacolaco)

docs.google.com

次は、lacolaco さんによる「いつテストを書くか?―ソフトウェア開発における安心と不安について考える」です。

AI コーディングでテストを作成することが増えた昨今、テストを書く目的を見失いつつあったので、改めてテストを書く意義を再認識するためにセッションを聞いていました。

テストという観点から開発の本質を問いかける

このセッションはテストを切り口にしながら、保守性の高いソフトウェア開発とは何か、そしてソフトウェアの変更容易性をどうやって担保していくか、という問いを投げかけてくるものでした。テストを「書くべきか・書かざるべきか」という話ではなく、開発者がコードの変更に対して抱く安心や不安という、もっと深層の感覚から捉え直していく流れがとても印象的でした。

感じたこと

今回の TSKaigi では TypeScript の歴史や型システム、ツールといった話題が多く語られていましたが、このセッションはそうした話題からは一歩離れた内容でした。だからこそ、ソフトウェア開発において本当に大事なことは何か、という普遍的なテーマに正面から向き合っていて、聞いていて深く考えさせられるセッションだったと思います。

そして個人的に一番おもしろかったのは、これはテストに関する話ではあるものの、TypeScript の型定義を設計するときにも似たような感性や着眼点が必要なのかもしれない、と感じたことです。「この設計に手を入れるのは怖くないか」「この構造に無理がないか」という変更に向き合うときの感覚は、テストを書くかどうかを判断するときにも型を設計するときにも同じように働いている気がします。テストの話を通して自分がコードとどう向き合っているのかそのものを見直すきっかけになりました。

次世代リンターで探る、tsgo 時代における型認識カスタムルールの現実解(Yuta Takahashi)

speakerdeck.com

最後は、髙橋佑太さんによる「次世代リンターで探る、tsgo 時代における型認識カスタムルールの現実解」です。

tsgo が来る時代に、型認識カスタムルール(Type-Aware Linting)とどう向き合っていくか、という非常に実務的なテーマでした。

tsgo で型情報へのアクセス境界が変わる

tsgo では型チェック処理が Go 実装側へ移るため、これまで TypeScript 本体から呼び出していた型情報へのアクセスが JavaScript 側からはできなくなります。

@typescript-eslint/no-floating-promises のように式の型を見て検出する型認識ルールは、今は typescript-eslint が担っています。parser services 経由で TypeChecker を引いて型情報をもとに診断する仕組みです。開発環境のエコシステムのひとつである Lint には、こうした TypeScript の型情報に依存したルールが存在します。

ところが tsgo では型チェック本体が Go 実装・ネイティブプロセス側に移るため、JS / TS で書かれた既存の ESLint カスタムルールは、従来の parser services 経由では tsgo 側の型情報を参照できなくなります。つまり各種 Lint ツールにとっては、型に依存する Lint ルールで「型情報を Go からどのように呼び出すか」が課題になる、というわけです。

次世代リンターの対応状況の整理

発表では、Oxlint(tsgolint をバックエンドに採用)、Rslint(Go 製で typescript-go を直接組み込み)、Biome(独自型推論の Biotype)という次世代リンターの対応状況が、表で丁寧に整理されていました。標準の型認識ルールはそれぞれ実装が進んでいる一方、型認識のカスタムルールはいずれも現状では未対応、という状況が一望できる内容でした。

その上で、Rslint にパッチを当てて型認識カスタムルールを Go バックエンドルールとして実装する PoC まで踏み込んでいたのが素晴らしかったです。実際に「書けるか」は検証できた一方で、typescript-go の internal API(GetAwaitedType などの unexported な API)に shim で依存することになり、内部実装の変更を自前で追従し続ける必要がある、という運用リスクも正直に共有されていました。「書けるだけでは代替できない」という指摘がとても誠実だと感じました。

各種 Lint ツールが tsgo にどのようにアプローチしているのかが表で整理されていたので、今後 Lint ツールを選定する上でも参考になるセッションでした。

まとめ

TSKaigi 2026 は、TypeScript 7 の tsgo という言語処理系の大きな節目と、AI とどう向き合って開発するかという、2 つの大きなテーマが並ぶカンファレンスだったように思います。

今回紹介したセッションはテーマこそ異なるものの、「AI がコードを書く時代に、人間は何を設計し、どこで責任を持つのか」という問いに向き合っていたように感じました。型設計、プラグイン設計、テスト、Lint ルールのいずれも、単なる実装技術ではなく、ソフトウェアを継続的に進化させるための意思決定そのものです。TSKaigi 2026 は、TypeScript の未来だけでなく、AI 時代のエンジニアリングのあり方についても考えさせられるカンファレンスでした。

紹介しきれなかったセッションもたくさんあるので、YouTube のアーカイブ動画が公開されたらぜひチェックしてみてください。

運営スタッフの方々、カンファレンスの開催・運営ありがとうございました。


是非読者になってください!


メドピアでは一緒に働く仲間を募集しています。
ご応募をお待ちしております!

■募集ポジションはこちら hrmos.co

■エンジニア紹介ページはこちら engineer.medpeer.co.jp

■メドピア公式YouTube  www.youtube.com

■メドピア公式note
style.medpeer.co.jp