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
TSKaigi Night Talks 2026_TypeScriptでサプライチェーンの整合...
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
ギークプラス ソフトウェア事業部
June 10, 2026
Programming
130
0
Share
TSKaigi Night Talks 2026_TypeScriptでサプライチェーンの整合性を型に閉じ込める
2026/06/10開催のTSKaigi Night Talks 2026の登壇資料
ギークプラス ソフトウェア事業部
June 10, 2026
More Decks by ギークプラス ソフトウェア事業部
See All by ギークプラス ソフトウェア事業部
会社説明資料|株式会社ギークプラス ソフトウェア事業部
geekplus_tech
0
630
ソフトウェア事業部のビジョン
geekplus_tech
1
75
インフラを Excel 管理していた組織が 3 ヶ月で IaC 化されるまで
geekplus_tech
3
260
Other Decks in Programming
See All in Programming
Oxcを導入して開発体験が向上した話
yug1224
4
280
次世代リンターで探る、tsgo 時代における型認識カスタムルールの現実解
ytakahashii
3
1.4k
CLIであることを活かしたGitHub Copilot CLI活用術 / GitHub Copilot CLI Pro Tips & Tricks
nao_mk2
1
1.2k
PHPで使える日時の表現と、その知り方 #frontend_phpcon_do
o0h
PRO
0
180
AI時代の仕事技芸論 — ソフトウェア開発で「遊ぶように働く」職人的熟達のすすめ
kuranuki
1
600
権限チェックの一貫性を型で守る TypeScript による多層防御
mnch
4
1.1k
OCRを使ってゲームのアイテムをデータ化する
kishikawakatsumi
0
130
TAKTでAI駆動開発の品質を設計する
j5ik2o
5
680
SPMマルチモジュールで テストカバレッジを取得する技法
yosshi4486
0
140
Copilot CLI の継戦能力を高める コンテキスト管理
nozomutu
1
1.2k
Lessons from Spec-Driven Development
simas
PRO
0
130
生成AI時代にこそ効くGo | Why Go Works in the Age of Generative AI
mom0tomo
8
3.1k
Featured
See All Featured
XXLCSS - How to scale CSS and keep your sanity
sugarenia
250
1.3M
GitHub's CSS Performance
jonrohan
1033
470k
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
2k
The Language of Interfaces
destraynor
162
27k
Reality Check: Gamification 10 Years Later
codingconduct
0
2.2k
Abbi's Birthday
coloredviolet
2
7.9k
The Pragmatic Product Professional
lauravandoore
37
7.3k
Music & Morning Musume
bryan
47
7.2k
svc-hook: hooking system calls on ARM64 by binary rewriting
retrage
2
280
The Anti-SEO Checklist Checklist. Pubcon Cyber Week
ryanjones
0
150
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
590
Building an army of robots
kneath
306
46k
Transcript
Moving the world intelligently ©Geekplus Co., Ltd. TypeScriptで サプライチェーンの整合性を 型に閉じ込める
株式会社ギークプラス Soju Kameyama | Web Engineer 2026.06.10
Moving the world intelligently ©Geekplus Co., Ltd. 2 ⾃⼰紹介 ⽒名
⻲⼭ 創樹(Soju Kameyama) 所属 株式会社ギークプラス ソフトウェア事業部 経歴 株式会社インフォマティクス 入社 キヤノン株式会社 入社 KINTOテクノロジーズ株式会社 入社 株式会社ギークプラス 入社 2017 2019 2022 2026 サプライチェーンに関わるお客様の業務を支援するSkylaaの開発を行っています 担当
INDEX Moving the world intelligently ©Geekplus Co., Ltd. 3 1.
同じ事実を別々に持つと、ズレる問題 2. 発想を変えてみる:保存するのは"流れ"だけ 3. まとめ 今回はバックエンドのお話になります
Moving the world intelligently ©Geekplus Co., Ltd. 4 1. 同じ事実を別々に持つと、ズレる問題
設計で悩んだ部分です
「品切れ」が上へさかのぼる例で考える ④発注先の⼯場から納品 (⼯場 → 倉庫) 100個 ⑤⾃社倉庫からお店へ転送 (倉庫 → お店)
100個 ①お店の棚が100個 品切れ!! Moving the world intelligently ©Geekplus Co., Ltd. ②転送依頼 ③発注依頼 この場合のモノの動きは2種類 = 「外部から取り寄せる(発注系)」と「内部で移動(転送 系)」 ⾃社倉庫 取引先メーカー
同じ100個の動きを、別々の表で⾒たい さきほどの“⼀連の流れ” (⼯場→倉庫→お店 / 100個の動き) Moving the world intelligently ©Geekplus
Co., Ltd. 「⼯場への発注リスト(⼯場→倉庫 100)」 「お店への転送リスト(倉庫→お店 100)」 「『品切れをどう埋めたか』全体の流れ」
システムで単純に表現しようとするとこんな感じに 「発注リスト」を保存? 「転送リスト」を保存? 「全体の流れ」も保存? 流れ Moving the world intelligently ©Geekplus
Co., Ltd. → 3つを 別々に組み⽴てて、別々に持つ?? ?
Moving the world intelligently ©Geekplus Co., Ltd. 整合性が崩れる罠 • 「転送リスト」だけ直して他を直し忘れる
→ 発注リスト‧全体の流れとズレる • 表を増やすたびに、 整合チェックのコードも増える 同じ事実を個別に持つと、バグの温床に
Moving the world intelligently ©Geekplus Co., Ltd. 9 2. 発想を変えてみる:保存するのは"流れ"だけに
設計を⾒直しました
話を戻すと さきほどの“⼀連の流れ” (⼯場→倉庫→お店 / 100個の動き) 「⼯場への発注リスト(⼯場→倉庫 100)」 「お店への転送リスト(倉庫→お店 100)」 「『品切れをどう埋めたか』全体の流れ」
Moving the world intelligently ©Geekplus Co., Ltd. どれも同じ「1本の流れ」を別の⾓度で⾒ているだけ →保存するのも1つで良さそう
Moving the world intelligently ©Geekplus Co., Ltd. 発想を変えてみる:流れだけ保存して、表は計算する 保存するのは「流れ」だけで各リストは流れからの計算 =
Reactの「派⽣stateは持たず計算する」と同じで、状態は1つ+表⽰は計算 ⼯場 → 倉庫 → お店 「⼀連の流れ」(唯⼀の正解) 関数で計算 (保存しない) 発注リスト 転送リスト 全体リスト その他記録 保存するやつ 計算で出すやつ ※ 物の移動 物の移動 物の移動 物の移動 物の移動
使う道具は、主に2つ 判別可能ユニオン 「この変数は、何種類かのうちのどれか1つ」という型 type Shape = | { kind: 'circle';
r: number } | { kind: 'square'; size: number } // 種類によってプロパティ構成も変えられる 各種類に⾒分けるためのラベル(タグ)がある 純粋関数 同じ⼊⼒なら、必ず同じ出⼒(外の状態に触れない) const add = (a: number, b: number) => a + b // DB や グローバルオブジェクト には触らない 結果が予測できる → テストが楽、どこでも再利⽤できる この2つを⽤いて 「流れ → 表」 を安全に組み⽴てることができる Moving the world intelligently ©Geekplus Co., Ltd.
流れは、2種類のノードでできた“⽊構造”と捉える 外から取り寄せる(発注) 中で運ぶ(転送) // 流れの中の1ノード(2種類) type Node = | {
kind: 'order'; // 発注 // ...(プロパティは省略) children: Node[] // 次のノード } | { kind: 'transfer'; // 転送 // ...(プロパティは省略) children: Node[] // 次のノード } 「種類は2つのうち1つだけ(判別可能ユニオン)」を型で宣⾔(取り違えはコンパイルエラー) ※スライド⽤に名前を簡略化しています Moving the world intelligently ©Geekplus Co., Ltd.
流れは、2種類のノードでできた“⽊構造”と捉える ※スライド⽤に名前を簡略化しています Moving the world intelligently // ノード定義(流れの中の1ノードにあたり、今回は2種類用意) type Node
= | {kind:'order'; from:string;to:string;qty:number;children:Node[]} | {kind:'transfer'; from:string;to:string;qty:number;children:Node[]} // ①「流れ」をこういう入れ子のオブジェクトに格納(実際には DBから取ってくる) const flow: Node[] = [{ kind: 'order', from: '工場', to: '中央倉庫', qty: 180, children: [ {kind:'transfer',from:'中央倉庫',to:'渋谷店',qty:100,children:[]}, {kind:'transfer',from:'中央倉庫',to:'新宿店',qty: 80,children:[]}, ], },] // ② 木を歩いて、指定した kind のノードだけ集める関数(純粋関数) function collect(nodes: Node[], kind: Node['kind']): Node[] { return nodes.flatMap((n) => [ ...(n.kind === kind ? [n] : []), // ← unionだからkindで絞り込める ...collect(n.children, kind), ]) } // 上記関数を使って注文リスト・配送リストを作成(表示用) const orderList = collect(flow, 'order') // 工場→中央倉庫 const transferList = collect(flow, 'transfer') // 中央倉庫→各店舗
さらに拡張すると(卸売業者パターン) Moving the world intelligently ©Geekplus Co., Ltd. 発注 転送
転送 転送 転送 転送 出荷 出荷 出荷 出荷 複雑な⽊構造も1つの流れとして組み⽴てることができる • 外部の会社に持ち出す「出荷型」を新たにNode定義(内から外) • ⽊構造なので枝分かれも表現できる ex.外部⼯場から親倉庫へ ex.親倉庫から⼦倉庫Aへ ex.⼦倉庫から孫倉庫へ ex.孫倉庫から外部⼩売業者へ ex.親倉庫から⼦倉庫Bへ
Moving the world intelligently ©Geekplus Co., Ltd. 16 3. まとめ
もう少しだけお付き合いください
まとめ ⼀連の物の流れにおいて、状態は1つだけ(⽊構造として)持つようにする そこから派⽣する値は保存せずに計算(純粋関数)で出すようにする 「状態は1つ、表⽰は計算」 → 改修時にズレを直すのではなく起こさないようにする Moving the world intelligently
©Geekplus Co., Ltd.
Moving the world intelligently ©Geekplus Co., Ltd. 18 ありがとうございました
©Geekplus Co., Ltd.