Slide 1

Slide 1 text

ドメインを組織の資産にする 少人数で複数プロダクトを支えるTypeScript運用の実践 TSKaigi 2026 Sponsor Session 須永 高弘 ©ASSIGN Inc. All Right Reserved.

Slide 2

Slide 2 text

自己紹介 • ⼤学卒業後、総合コンサルファームに⼊社し、 主に製造やメディアの顧客に対して 戦略、業務、ITに掛かる多様なプロジェクトを経験 • 若⼿転職⽀援アプリ「ASSIGN」の開発・運⽤、 LLMの事業活⽤、エンジニア組織開発等に従事 執⾏役員CTO 須永⾼弘 Takahiro Sunaga ©ASSIGN Inc. All Right Reserved. 1

Slide 3

Slide 3 text

会社概要 ©ASSIGN Inc. All Right Reserved. 1

Slide 4

Slide 4 text

©ASSIGN Inc. All Right Reserved. 1

Slide 5

Slide 5 text

©ASSIGN Inc. All Right Reserved. 1 事業フェーズと業務特性に合わせて、個別に開発してきた 業務特性も事業の成り立ちも違うため、個別開発でスタート

Slide 6

Slide 6 text

1つの語彙が複数の画面・業務処理に使われるほど、変更時に揃える範囲が広がる 同じ業務語彙でも、利用者ごとに関心が変わる ©ASSIGN Inc. All Right Reserved. 1

Slide 7

Slide 7 text

状態を1つ追加するだけでも、型・表示・検証・通知条件まで揃える必要がある 業務変更は、画面・API・通知まで波及する ©ASSIGN Inc. All Right Reserved. 1

Slide 8

Slide 8 text

1 影響調査 どの画面・API・通知に影響するかを追う 例: 状態追加で UI / hooks / schema / 通知条件まで確認する 2 整合作業 値・型・表示・検証・通知条件を揃える 画面だけ、APIだけ、通知だけが古い状態を残さない 3 設計検討の 反復 追加開発のたびに、同じ設計検討や判断を繰り返す 過去の判断理由を探し、似た議論をもう一度やり直す 業務変更のたびに、調査・整合・設計検討が繰り返される ©ASSIGN Inc. All Right Reserved. 1

Slide 9

Slide 9 text

方針 減らしたい負荷 実装でやること 1. 境界で検知する API変更の追従漏れ、不正な外部値の 混入 API契約・外部値の入口で失敗させる 2. 業務語彙を集約する 画面・API・通知の整合 型・schema・定数・ラベル・変換・ 判定を shared domain に寄せる 3. ドメインを再利用する 同じ設計検討・判断の反復 根幹ドメインを 共通package にし、 過去の設計を次の開発で参照する 調査・整合・設計検討を、コード上の仕組みに落とす ©ASSIGN Inc. All Right Reserved. 1

Slide 10

Slide 10 text

選考プロセスの型・表示・検証・判定を、Web/APIが参照できる入口にする 新卒業務システム モノレポ内に、画面・APIが共通参照でき るdomainを用意 apps/ web api packages/ shared/ domain/ selectionProcess.ts applicationChannel.ts → selectionProcess.ts 変更時に確認する型・表示・検証・判定を一箇所に寄せる 定義 役割 例 schema / 型 入出力の形 Web/APIの入出力を同じ形で扱う SelectionProcess CreateWireSchema 状態値 選べる状態 追加・削除される業務状態を一覧 化する SELECTION_PHASES SELECTION_STATUSES label / options 画面表示 表示名・選択肢を揃える getLabel() getOptions() parse / validate 外部値の検証 Form/URL/API値を入口で検証す る parseFromWire() rule / predicate 業務判定 終了判定・報告条件を画面から切 り離す isSelectionEnded() canCreateAssignRequest() 業務語彙をshared domainに集約する ©ASSIGN Inc. All Right Reserved. 1

Slide 11

Slide 11 text

共通の型・schema・状態値を参照することで、画面とAPIの変更漏れに気づきやすくする Webフロント 型で画面の扱いを揃える 状態値を型で扱う as const で定義した状態値 を参照し、選択肢・表示名の 未対応を見つけやすくする 状態ごとの扱い漏れを検 知する satisfies で状態値ごとの ラベルや分岐を確認し、新し い状態の扱い漏れを見つけや すくする 参照 ← packages/shared/domain/ selectionProcess.ts 画面とAPIが共有する業務語彙の契約 選考プロセスの型 画面とAPIで扱うデータの形 状態値の定義 選考フェーズ・ステータス・表示名 外部値の受け入れ条件 FormやAPI由来の値を扱えるか 業務判定 選考終了・報告前提などの共通ルール → 参照 API schemaで境界の扱いを揃える 入出力を型で固定 generated types や z.infer で request / response を扱 い、API変更時の修正漏れを検知 しやすくする 外部値を検証 Zod parse でURLやForm由来の 値を検証し、不正な値を domain の手前で止める shared domainを参照して、画面とAPIの整合を保つ ©ASSIGN Inc. All Right Reserved. 1

Slide 12

Slide 12 text

共通して扱う型とルールを切り出し、関連プロダクトで使える設計資産にする 中途・新卒の根幹ドメインを共通packageにする ©ASSIGN Inc. All Right Reserved. 1

Slide 13

Slide 13 text

共通packageに型と判定を置き、adapterで変換、個別実装で固有フローを書く 新卒支援業務システム プロダクト内に adapter 層と個別実装を分けて持つ 個別実装 新卒固有の後続業務 共通判定のisAcceptedOfferを使い個別フロー を書く 型・値・判定を共通化し、変換と固有業務は個別に実装する @assign/career-domain 共通ID・内定結果・判定関数を置く branded typesでIDの取り違えを型で防ぐ zodで実行時の値を検証し、z.inferで型として扱う type Brand = T & { readonly __brand: N } export type CandidateId = Brand export const OfferOutcomeSchema = z.enum([ "none", "offered", "accepted", "declined", "joined", ]) export type OfferOutcome = z.infer export const isAcceptedOffer = (v: OfferOutcome) => v === "accepted" adapter 状態値を共通ドメイン値へ変換 satisfiesで状態値の変換漏れを検知する const outcomeByStatus = { noOffer: "none", accepted: "accepted", declinedAfterAcceptance: "declined", joined: "joined", } satisfies Record< NewgradOfferStatus, OfferOutcome> export const toCareerOfferOutcome = ( status: NewgradOfferStatus, ): OfferOutcome => outcomeByStatus[status] export const getPostAcceptanceActions = ( outcome: OfferOutcome, ) => { if (!isAcceptedOffer(outcome)) return [] return [ "confirmGraduationYear", "scheduleOfferEvent", ] } ©ASSIGN Inc. All Right Reserved. 1

Slide 14

Slide 14 text

成約報告判定のような根幹ロジックを、新卒と中途で同じ定義から呼び出せる 既存の状態値や業務フローを保ったまま、根幹ロジックを共通化できる ©ASSIGN Inc. All Right Reserved. 1

Slide 15

Slide 15 text

プロダクト内で業務語彙の参照元を一箇所にする shared/domainに型、schema、業務ルールなどを集約し、画面・APIの不 整合や変更漏れを減らす 関連プロダクト間で根幹ドメインを再利用する common package + adapterで根幹ドメインを共通化し、固有フローを個 別実装に残して関連プロダクトで再利用する 蓄積したドメインから、次のプロダクトを始める 既存の業務語彙・型・業務ルール・変換処理を活用して、新たなシステム 開発を始められるようにする 蓄積したドメインから、次のプロダクトを始める 業務語彙 の集約 根幹ドメイン の共通化 新規プロダクト への展開 ©ASSIGN Inc. All Right Reserved. 1

Slide 16

Slide 16 text

ブースのご案内 採用情報 ポジション情報 カジュアル面談 ご案内 ©ASSIGN Inc. All Right Reserved. 1

Slide 17

Slide 17 text

ご清聴ありがとうございました ©ASSIGN Inc. All Right Reserved. 1