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
関係性から理解する"同一性"の型用語たち
Search
pvcresin
May 22, 2026
Programming
630
2
Share
関係性から理解する"同一性"の型用語たち
TSKaigi 2026
https://2026.tskaigi.org/talks/6
pvcresin
May 22, 2026
More Decks by pvcresin
See All by pvcresin
リセットCSSを1行消したらアクセシビリティが向上した話
pvcresin
4
540
Reduxモダナイズ 〜コードのモダン化を通して、将来のライブラリ移行に備える〜
pvcresin
2
940
text-box-trim について 1 分で
pvcresin
0
150
Web IDEの進化とそれを支える技術
pvcresin
0
140
ステップアップOSSコントリビュート
pvcresin
0
500
Webアプリケーションのアーキテクチャパターンから読み解くNext.js
pvcresin
0
450
Eight WebフロントエンドのDX向上に関する取り組み
pvcresin
0
210
TS 未経験者が 社内向け JS ライブラリを TS に置き換えている話
pvcresin
0
430
React はじめの一歩
pvcresin
1
270
Other Decks in Programming
See All in Programming
AIチームを指揮するOSS「TAKT」活用術 / How to Use “TAKT,” an OSS Tool for Orchestrating AI Teams
nrslib
6
800
技術記事、AIに書かせるか、自分で書くか? 〜それでも私が自分の手で書く理由〜 / #QiitaConference
jnchito
2
1.3k
AI時代の仕事技芸論 — ソフトウェア開発で「遊ぶように働く」職人的熟達のすすめ
kuranuki
1
600
並列実装の現場、2ヶ月間実務でAIを使い倒したAIもPCも私も限界が近い
ming_ayami
0
100
気づいたらRubyで100作品 ー クリエイティブコーディングが生活の一部になるまで / 100 Ruby Sketches Later: How Creative Coding Became Part of My Life
chobishiba
3
530
Old Dog, New Tricks: The Java 25 Reinvention - JNation
bazlur_rahman
0
140
AIエージェントと協働するCLI開発 — BunとOpenClawで学んだこと
yoshikouki
1
230
3Dシーンの圧縮
fadis
1
590
プロパティの順序で型推論が壊れる!? TypeScript6.0の修正からContext-Sensitivityの仕組みを追う
bicstone
2
1.3k
開発体験を左右するライブラリの API 設計 - GraphQL スキーマ構築ライブラリから考える #tskaigi
izumin5210
2
1.6k
New "Type" system on PicoRuby
pocke
1
430
Datadog × OpenTelemetry 入門と実践のあいだ
kn_to_maxpno
1
130
Featured
See All Featured
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
140
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
231
23k
Being A Developer After 40
akosma
91
590k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
550
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
300
The Spectacular Lies of Maps
axbom
PRO
1
780
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
200
74k
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
65
56k
Neural Spatial Audio Processing for Sound Field Analysis and Control
skoyamalab
0
310
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
370
Transcript
関係性から理解する "同一性"の型用語たち pvcresin TSKaigi 2026
pvcresin 仕事 SansanでEightのWebエンジニア 興味 フロントエンド/デザイン/型 言語 TypeScript/Kotlin/Ruby 自己紹介
TypeScriptの話題において、nominal / structural / branded / opaque / phantomといった 型に関する用語を見かける機会が増えてきました。
しかし、これらの違いや関係性を説明しようとすると曖昧になりがちです。 私自身も「なんとなく分かったつもり」で流してしまった過去があり、 後からうまく説明できずに後ろめたさを感じる場面がありました。 本発表ではTypeScriptが構造的型付けであることを起点に、 型の同一性に関するこれらの用語を、コード例を交えて紹介します。 そのうえで、これらの違いと関係性を理解し、解説記事や議論を追える状態を目指します。 トーク概要
この発表のスコープ 話さないこと 話すこと - コード例を交えた型用語の解説 - それぞれの用語の関係性の整理 - 特定のライブラリの使い方
型の同一性 A型の値を、 B型の値に代入できるか
アジェンダ - Nominal/Structural - プリミティブ型に関する課題 - Branded/Opaque/Phantom - まとめ
Nominal/Structural
Nominal/Structural Nominal Typing(名前的型付け) - 公称型とも呼ばれる - 名前や継承などで型を判別 - Java, C#,
Kotlin, Go(struct)など Structural Typing(構造的型付け) - 構造的部分型とも呼ばれる - 構造で型を判別 - TypeScript, Go(interface)など
Structural Typing Nominal Typing クラス
type aliasはほとんどの言語で透過的 プリミティブ
Goのdefined typeはNominal プリミティブ
トレードオフ Nominal Structural 構造が同じ値の取り違え ✅ 名前で判別できる ❌ 混ざる可能性がある 別の型として渡す ❌
変換が必要 ✅ 構造が合えば渡せる
Duck/Goose
Goose Typing - 実行時に対象の値が特定のクラスに 属しているかで型を判定 - Python(ABC + isinstance), Ruby(is_a,
kind_of, instance_of), JavaScript(instanceof)など Duck/Goose Duck Typing - 実行時にその値が特定のメソッドや プロパティを持っているかで型を判定 - コードの再利用性を高められる - Python, Ruby, JavaScriptなど
Goose Typing Duck Typing Duck/Goose ※ 呼び出し前に事前チェックする場合 ※ PythonのABC相当なし
JavaScriptでのDuck Typingを静的な型に自然に落とし込むためには、 TypeScriptはStructuralな型システムである必要があった ここまでのまとめ 名前で判別 構造で判別 コンパイル時 Nominal Structural 実行時
Goose Duck
プリミティブ型に関する課題
プリミティブ型に関する課題 - 手軽に使えるため、プリミティブな値で管理する場面は多い - ID(UserId, GroupId, …) - 単位(JPY, USD,
…) - 特定の文字列(Email, URL, …) - すべてがstringやnumberに潰れがちで、取り違えのリスクが高い - 一方、クラスは構造がユニークになることが多く、問題になりづらい
Branded
- 識別子となるプロパティを混ぜて、型を判別可能にする実装パターン Branded Type(ブランド型)
- クラス - オブジェクト - プリミティブ プリミティブな値を判別するアプローチ
- 両方とも中身が同じstringなので 判別できない - あ - あ - あ 元コード:
プリミティブな type alias
- クラスは通常Structuralに判別 - 固有の変数を持つ場合はNominal - private, protected修飾子 - JavaScriptの#private field
- 実行時オーバーヘッド クラス + private - あ - あ - あ
オブジェクトにネスト + string literal - オブジェクトにネストし、値の型を判別するための情報を追加する - 型をasで宣言することで、value以外に追加で__brandを設定しなくて済む - 実行時にオーバーヘッド
- プリミティブな値をそのまま使える - 実行時への影響がない プリミティブ + オブジェクト交差
プリミティブパターン良さそう 現状のコードだとまだ課題がある - __brandキーがstringなので、IDEの補完に出る/他コードと衝突しうる - 本当に欲しいのは 補完を汚さない/衝突しない/文字列で触れないキー
衝突しない brandプロパティを作るなら Symbol Symbol - 必ず一意になるプリミティブ(型はunique symbol) - プロパティのキーに使うことで、補完を汚さず、不正なアクセスも防ぐ
- 実行時に値を生成しないよう、Symbol()で実体を作らずにdeclare const - 衝突なし・補完に出ない・不正にアクセスができないbrandプロパティ - モジュール内では__brandに代入が可能なため、readonlyで上書き防止 キーを unique symbol
+ readonly にする
- 識別子となるプロパティを混ぜて、型を判別可能にする実装パターン 【再掲】Branded Type(ブランド型)
Opaque
Opaque Type(不透明型) - 型の実体を外部に教えず、生成口を絞る運用パターン(=カプセル化) - Scala, Swift, Flowなど
Opaque Type(不透明型) - TypeScriptには as 制限などの隠蔽機能がない - 「Branded Type +
生成口を1点に絞る運用」と捉えるのが現実的
Phantom
- 状態を表す型パラメータで判別 - 渡した型パラメータが、値の表現には 現れない - Haskell, Scala, Kotlinなど Phantom
Type(幽霊型)
代入できてしまう 素直にTypeScriptにすると
privateを導入して Nominalにすると実現可能
クラスにしないでも実現可能
まとめ
型用語の関係性 実装に使う 生成口絞る Branded Type (ブランド型) 識別子を混ぜて型を判別 Opaque Type (不透明型)
型の実体を外部に教えない Phantom Type (幽霊型) 状態を型パラメータで持つ 判定タイミング 判定方式 Structural Typing (構造的型付け) 構造で型を判別 Nominal Typing (名前的型付け) 名前で型を判別 Goose Typing 実行時に 名前で型を判別 Duck Typing 実行時に 構造で型を判別 判定方式 Nominal模倣
- TypeScriptはStructural Typingだが、型の表現力でNominalを模倣できる - Branded Typeを活用すれば、実行時への影響なく型安全性を高められる - 実装は同じ見た目でも、用語によって重視する概念が異なる まとめ
None