Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
400超のデータポイントを型で制す — UPSIDERの与信審査エンジンを支えるTypeScr...
Search
UPSIDER, Inc. Tech&Product div.
June 11, 2026
760
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
400超のデータポイントを型で制す — UPSIDERの与信審査エンジンを支えるTypeScriptの「柔軟性」と「結合力」_泉雄介
TSKaigiでVPoE泉が登壇した資料です。
https://2026.tskaigi.org/talks/39
UPSIDER, Inc. Tech&Product div.
June 11, 2026
More Decks by UPSIDER, Inc. Tech&Product div.
See All by UPSIDER, Inc. Tech&Product div.
なぜレスポンスボディを読み切るのか - Go 1.27で進化した net/http のコネクション再利用メカニズム_Ryu
upsider_tech
1
95
エンジニアはどこまで越境するべきか_Take
upsider_tech
9
3.4k
『⽌めない』を設計する 制約の中で、事業の根幹を⽀える判断_terry
upsider_tech
0
33
English for Shy Engineers
upsider_tech
0
120
時価総額から逆算する、日々開発価値_ PL/BSで読み解くエンジニアリング貢献_Kinsho
upsider_tech
1
200
最近、評価が難しくなった ── 変わったのは評価項目ではなく、見方と見せ方_Mitsui
upsider_tech
0
37
TypeSpecで繋ぐ複数プロダクトの型安全 — スキーマ共有による「型契約」の実践_mitsui
upsider_tech
0
33
フルスタックTypeScriptで挑む、UPSIDER法人審査システムの再構築_Mitomi
upsider_tech
0
410
TypeScriptの型はAIに届いている か?_shotaro
upsider_tech
1
1.8k
Featured
See All Featured
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
390
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.6k
Evolving SEO for Evolving Search Engines
ryanjones
0
300
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
990
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
480
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.2k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.4k
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
550
What's in a price? How to price your products and services
michaelherold
247
13k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
30k
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
1
530
Making the Leap to Tech Lead
cromwellryan
135
10k
Transcript
400超 データポイントを型で制す UPSIDER 与信審査エンジンを支えるTypeScript 「柔軟性」と「結合力」 泉 雄介 — VPoE, UPSIDER
自己紹介 アメリカ 音楽大学を卒業後、メディア制作会社で作曲家とし て勤務した ち、システム開発で起業。 モルガン・スタンレー証券会社で 債券取引 システム開発 や、ディー・エヌ・エーにおけるゲームプラットフォーム事業や ヘルスケアサービス開発
リードエンジニア、ラクスル取締 役CTOを経て、株式会社UPSIDERに入社しVP of Engineeringを務める。 言語: Go / TS / Ruby / Perl / C# / JS / Java / PHP CFA協会認定証券アナリスト (2011~) 日本CTO協会理事 (2024~) グロース市場企業社外取締役(2025~)
UPSIDER Inc. 「挑戦者を支える、世界的な金融プラットフォームを創る」 というミッション もと、 「UPSIDERカード」を じめ、様々な「利用しやすい」法人向け金融サービスを展開してきた。
UPSIDER 審査規模・体制 1 取扱企業 数万社規模 日々更新 2 特徴量 1審査あたり 400
超 データポイント 3 ロジック 4系統 x 系統毎 20以上 チューニング パラメータ 4 運用体制 少人数で 高機能運用 5 開発体制 PdM x 1, App x 1 Data Eng x 1, DS x 1
審査アーキテクチャー
Java で書け 安全だが重い Backend Technology VS JS で書け いが危ない 「型付け言語とJS由来
柔らかさ」
可視化・審査 UX 1. 基本情報 2. 財務情報・入出金明細 3. 残高・バーンレートシミュレーション 4. 支払い・延滞情報
5. そ 他特徴量 可視化や審査UXも重要!
業界 常識 vs 現場 要件 VS 業界 常識 (金融ドメイン )
Java / Kotlin / Scala / Go 等による堅牢な実装 安定したデータモデル 一度決めた構 慎重に変更する レイヤーごと 厳密な分割 各層で専用 DTOを持ち同期する UPSIDER 現場要件 TypeScript + Zod 堅牢性とアジリティを両立 変化する審査ロジック 市場変動に合わせて動的に変えたい システム全域 貫通 1つ スキーマでDBからUIまで結合する 技術選定 変更頻度 アーキテクチャ
TSがもたらす5つ 強み 1 400 特徴量を「1つ 型」に閉じる 2 ロジックがデータになる(動的Override) 3 Strategyパターンによる審査処理
切り替え 4 フロントとバックエンドを繋ぐ「1 Interface」 5 AIと 相性(おまけ)
1 400 特徴量を「 1つ 型」に閉じる
スキーマ宣言を「 1回」で済ませる export const zFeatures = z.object({ banks_avg_balance: z.number(), dpd_over_30:
z.boolean(), banks_burn_slope: z.number().nullish(), banks_concentration_inflow_1m: z.number().nullish(), // ... 400 lines ... current_credit_line: z.number().nullish(), dpd_over_30_within_36_months: z.boolean().nullish(), }) export type IFeatures = z.infer<typeof zFeatures> 1. コンパイル時 型定義 (IFeatures) 2. 境界 ランタイム検証 (z.parse) 3. 部分型へ 派生 (zFeatures.partial()) 4. JSONシリアライズ対応
もしJavaで同じことを書いたら? HTTP Domain Persistence Wiring / Test FeaturesRequest Bean Validation付き
API用DTO Features Record Immutableなドメインモデル FeaturesEntity & Converter JPAとJSONBカラム 変換 FeaturesMapper & Builders MapStruct等で 型変換・テスト 1つ 概念に 8つ以上 ファイル が飛び散る摩擦
もしPure JSで書いたら? 実行時までキー typo に気づかない恐怖 features.dpd_over_30_within_36_month (末尾s抜け) 何も言わずに undefined ですり抜け、金額計算で
NaN 事故に。 与信 「1桁 ミス」 補填で 済まない損失になる。
2 データ 動的マージ
「What-if分析」 要件 動的マージにより、本番と全く同じロジックでパラメータや特徴量を変えたテスト・シミュレーションが実行可能 PostProcess Model Parameter 生成 特徴量 抽出 計算
結果 { 決定与信枠、自動承認 判定 } Parameter Injection ・X以上 スコアで自動承認 ・最低X円以上 与信枠 など 閾値や既定値を上書き Feature Injection ・個社ごと 固有 特殊事情 ・特定 属性値 一時的な変更 など 特徴量を上書き ビジネス影響 シミュレーション ポリシー(パラメータ)変更によって、 全 体 与信枠金額にど ような影響が あるかを計算可能。 個別 特徴量変更による個社へ 影 響 テスト・試算も本番と同じプロセス で検証できる。
コードで見る動的マージ 実装 「自動で動く本流」 特徴量と「手動介入(DB設定値)」 オーバーライドをマージする実際 処理 // DB設定値 (JSON列) 用
スキーマ export const zServiceProvisionConfig = z.object({ featureOverrides: zFeatures.nullish(), predictionOverrides: zPredictionModelResponse .partial().nullish(), }).strict() // → 完全に型付けされた overrides が手に入る // マージ実行 (predictProcedure.ts) const mergedFeatures = { // 本流 入力 ...input.features, // DBから オーバーライドをマージ ...(serviceProvision.configuration?.featureOverrides || {}), } 「JS スプレッド構文 気軽さ」を保ちつつ、「静的型推論」と「 Zod 境界検証」で守る
動的マージと静的型 両立 1. モデル全体 デフォルト DB 2. 今回 審査だけ 上書き
DB 3. Zodによる境界検証 (.parse) 完全に型付けされ、制約を満たした値として下流へ
実行時 想定外をシャットアウト Java 限界 Optional<Builder> 連鎖 何層にも重なるマージ ビジネスサイドに 説明できないコードに陥る 「上書きしたつもりが
出来ていない」バグ 温床 Pure JS 危険 スプレッド構文 {...a, ...b} タイポや未定義オブジェクト によるマージ失敗を 静的に弾けない 値が文字列 ままマージされ 計算時に NaN を誘発 TS Zod 解 マージ 柔軟性 JS まま 境界に来た瞬間に型と制約を検証 数値 範囲制約も実行時に保証 想定外 キー .strict() で拒否可能
3 Strategyパターンによる審査処理 切り替え
なぜ Strategy Pattern を用いる か? UPSIDERで 複数ブランドや特殊案件に応じた多様な審査パターンが存在。 「入出力 型 同じまま、内部
計算ロジックだけを柔軟に切り替える」設計が必要。 審査プロセス開始 INPUT 共通 型) ML予測審査パターン 1 UPSIDERカード等 ) ML予測審査パターン 2 PRESIDENTカード等 ) 上場企業・特殊案件用審査 (各種特化ロジック ) 後続プロセス OUTPUT 共通 型) 入出力 型制約 担保 したまま、中身 計算ロジックだけを動的に Switchできる
具体 実装 switch (method.postAppraisalProcess) { case PostAppraisalProcess.DEFAULT: return new DefaultPostProcessor().run()
case PostAppraisalProcess.RUNWAY: return new RunwayPostProcessor().run() default: // 型による網羅性 強制 const _exhaustive: never = method.postAppraisalProcess throw new Error(`Unsupported`) } ▪ Exhaustiveness Check enumに新しい値が追加されたとき、 switch文で処理が漏れているとコンパイル エラーとして検知。 ▪ 安全なStrategy分岐 ロジック追加時 「処理漏れ」を人間で なくコンパイラが確実に防ぐ。 ▪ 堅牢性へ アプローチ Java 21 sealed interface + pattern matching と同等 安全性をシンプル な文法で実現。
新しい審査パターン 追加コスト Interface実装 追加 IAppraisalPostProcessor を満たすクラスを作成 1 Switch文へ 追加 コンパイラが漏れを検知。
既存処理 破壊も防ぐ。 2 構 的型付けと Interface 恩恵により、低コストで安全に ロジックを拡張可能。 テスト審査 テストモードで新しい審査 パターンで結果を確認して適用 3
4 フロントとバックを「 1 Interface」で
OpenAPI生成モデルと 決別 従来 Java+JS開発 DB Entity DTO / Response Model
OpenAPI 仕様 生成 Generated TS Model tRPC Zod バックエンド Zod スキーマ フロント Mutation 型 コンパイル時 推論 みで直結
5 AIと 相性(おまけ)
どこに時間を使うようになったか? 1. PRDを書く 3. 3050分くらいAIに頑張ってもらう 2. 穴が空くほどレビューする 4. テストにより時間をかける
開発現場に見られる兆候 1Pizza Team チームサイズを 2-Pizza (7〜8人) から 1-Pizza (2〜3人) へ縮小。
エンジニアがAIを駆使して広範囲をカバーする ため、コミュニケーションコストが劇的に下が る。 巨大なPull Request 人間が介在せず、AIに自律的にコーディング させるため、PRが肥大化する。 しかし、型 境界が守られているため 「それ で良し」とする新しい開発スタイル。 人間 役割シフト 不要になるタスク: コーディング、単体テスト 集中すべきタスク: 要件定義、アーキテクチャレビュー、結合テ ストなど上流工程へシフト。
TypeScript 、ビジネス 武器 にできる 「静的型付け言語とJS由来 柔らかさ」 型システムを1言語に閉じたまま "守り" と "攻め"
を同時に行える。 少人数で複雑な審査プロセスをメンテできる。
Thank You 泉 雄介 VPoE, UPSIDER TSKaigi 2026