Upgrade to Pro — share decks privately, control downloads, hide ads and more …

バックオフィスに染み出すTypeScript ── clasp で安全に仕組みを作る

Avatar for Nealle Nealle
October 31, 2026

バックオフィスに染み出すTypeScript ── clasp で安全に仕組みを作る

TSKaigi Sendai 2026 登壇資料
https://sendai.tskaigi.org/talks/6

バックオフィスまわりの業務を改善しようとすると、独自のインフラ/システムを立てるほどではない、という判断になりがちで、結果としてスプレッドシートと手作業のところで止まりがちです。
そこでGoogle Apps Script を TypeScript + Clasp(3系) で書くようにしたところ、スムーズに開発ができました。
実行基盤がGAS のままであれば、デプロイ先を用意しなくてよく、定期実行はトリガーで済み、認証や権限は Workspace にそのまま乗ります。
その上で型を意識した堅牢なシステムが作れます。
社内向けのシステムを作る上で、一番面倒な部分を省略できるのが、この構成の利点だと思っています。
実際に作ったシステムを題材にバックオフィス改善におけるTypeScriptの利点やトレードオフをお話しします。

Avatar for Nealle

Nealle

October 31, 2026

More Decks by Nealle

Other Decks in Technology

Transcript

  1. ⾃⼰紹介 株式会社ニーリー DevHR 榎本 陽祐 えのもと ようすけ 物流‧⾦融領域の⼤規模システム開発を経て、医療介護スタートアップに 1 ⼈⽬のエンジニアとして参画。

    開発組織全体の責任者として技術⽅針から 採⽤まで担当。 2025年12⽉、ニーリーに1⼈⽬の DevHRとして⼊社。 𝕏 @motumotuo
  2. 1 採⽤⼯程におけるバックオフィスの課題 例えば、エントリーのたびにこれらを⼿作業していました Step 1 Step 2 ATS に新しい エントリー

    が来る ATS ATS アプリ ➞ Step 3 選考ステップを 書類選考 に変える ➞ 求⼈の担当者に 評価を依 頼する 18:02 〇〇株式会社 採⽤担当さんから推薦がありました。 候補者ID | 年齢 性別 | 求⼈名 〇〇株式会社 求⼈ごとに担当者が違う上、複数⼈がアサインされることも… これを⼈が毎回確認しながら 操作していました。 1 件の返信 採⽤担当 18:32 @評価者A @評価者B お疲れ様です! 書類選考 お願いいたします ※ Slack のイメージ
  3. 1 採⽤⼯程におけるバックオフィスの課題 どこで動かすか ⾃前でサーバーを⽴てる 作ること⾃体はできる。 ただ、実⾏ 環境、シークレット、 権限、監視を 誰が⾯倒を ⾒続けるのかという問題

    が残る。 結論 GitHub GitHubActions Actions 定期実⾏だけで設定を変えなければ 良い選択肢にはなり得る。 ただし、Actionsの実⾏コストには留 意する必要があるのと、再実⾏に⼀ 定の知識が必要 GAS とスプレッドシートで作ることに! GAS + スプレッドシート 割り当てルールを変えるのも、 結果 を確認するのも採⽤担当。 リポジトリの設定ファイルや Actions の画⾯を ⾒てもらう必要も なく、慣れたWorkspace上で操作で きる。
  4. 2 なぜ GAS × TypeScriptにしたのか そもそもclaspとは何か? Google が公開している、GAS をローカルで開発するためのコマンドラインツール。 ローカルで書いたコードを

    GAS のプロジェクトに push 可能。 Step 1 Step 2 TypeScriptを使ってローカルで ➞ 開発できる!!! (ということは型もサポートされる🎉) clasp pushでGASへ反映。 (変更履歴もGitから追えるし、万⼀の 時にも戻しやすい)
  5. 2 なぜ GAS × TypeScriptにしたのか clasp 3から普通の TS プロジェクトとして作れるようになった TS

    の変換は clasp ではなく⾃分のビルドで⾏い、clasp は dist を push するだけになった clasp 3 系 clasp 2 系まで ➞ clasp 内蔵の変換器で TS を変換 TypeScript のバージョンは古いまま固定 バンドラーで変換してから push ビルドは普通の TS プロジェクトと同じ 01 02 03 最新の TypeScript を使える import / export と npm が使え る テストと同じコードを動かせる バージョンを⾃分で選べるので、satisfies などの新しい構⽂も使える バンドラーが1ファイルにまとめるので、 types.ts / client.ts のように分けられる ※全てのnpmモジュールに対応している わけではない tsc --noEmit や vitest を普通の構成で回せ る。テストしたコードがそのまま GAS で 動く
  6. 2 なぜ GAS × TypeScriptにしたのか clasp でコード管理も全社の仕組みに乗せられる GAS エディタで直接書く clasp

    + GitHubで管理 • コードはスクリプトの中にしかない • コードは会社の GitHub org にある • Git の履歴もレビューも残らない • Git の履歴が残り、PR でレビューできる • 書いた⼈がいなくなると誰も触れない • Orgの Actions に乗ることができる(後述)
  7. 2 なぜ GAS × TypeScriptにしたのか つまり開発組織の仕組みに、 GAS のコードも相乗りできる! 例えばニーリーではorgレベルで全てのリポジトリに対して、GitHub ActionsのSHAピン留めや

    コミットメッセージやソースコードに対するPIIの検知を実施しています。 Pushしてはいけない情報をブロック サプライチェーン攻撃対策の⼀環として secret や PII を検知する仕組み GitHub ActionsのSHA Pinningを検査 万が⼀、API キーや候補者の個⼈情報をコミットしても すぐに気づいて対応できる仕組みがある。 GitHub ActionsがコミットSHAで固定されているかをCIに より検知し、リポジトリのタグが改ざんされるリスクを防 いでいます。 つまり⾃分で仕組みを⽤意しなくても、 バックオフィスのコードが開発組織と同じ基準で チェックされるのでセキュリティ観点からも安⼼して開発できます!
  8. 2 なぜ GAS × TypeScriptにしたのか 実はGAS でもこれらの機能は(それなりに)実現できる 必要なもの GAS での対応

    定期実⾏ 時間主導トリガー(ただし設定したユーザーの権限で動く制限あり) 外部サービスのAPIキーなどの管理 Script Properties 認証‧権限管理 認証は会社の Google Workspace アカウントがベース。 認可に関する細かな制御は⾃前で実装。 設定とログの閲覧や操作 スプレッドシートへ吐き出すこともできる。 (もしくはGoogle Cloudと紐づければCloud Loggingでも確認可能) DevHRがAWSなどのクラウドインフラまで作り始めると、周りの⼈(組織)のキャッチアップも⼤変になると思い、 バックオフィスのユーザーはいつもの Workspace で操作‧閲覧ができることを優先しました。
  9. 2 なぜ GAS × TypeScriptにしたのか エディタで直接書くよりもCIを通じた品質保証もやりやすい GAS エディタで直接書く TypeScript+clasp •

    確認は実際に動かして⽬で⾒ることが多い • vitest でテストを書ける • シートや API に依存して、⼿元で再現しにくい • GAS の API はモックに差し替えて⼿元で動かせる • 直すたびに本番のデータで試すことになりがち • push する前に動きを確認できる
  10. 3 事例:書類選考自動アサインの仕組み 1時間ごとに、書類選考の割り当てまでを自動で行う 01 GAS ※ 04 → 05 の順にしている理由

    autoAssign 評価依頼は送ると取り消せないため、先にス テップを変えておく 1時間ごとに起動 02 04 候補者を取得 ATS ステップ変更 対象求人の entry の 候補者 スプレッドシート 書類選考に変える 05 評価依頼 担当者に 依頼を送る 03 06 担当者を調べる ログに記録 求人ごとの 担当者を 参照 結果を ログシートに 残す ATS の機能で Slack ※ エラーハンドリング どのステップで失敗しても、Slack に通知する 評価者へ通知 Slack に 依頼が届く
  11. 3 事例:書類選考⾃動アサインの仕組み 型が活きている場所は主に2か所 ⼊⼝ データを作るのは やっていること ATSのAPI ATS(形式が決まっている) 型を宣⾔して、キャストは1か所だけ 職種と担当の

    マッピングシート 採⽤担当(⼿で⼊⼒する) unknown で受けて、1セルずつ変換 ⼈が⼿で⼊⼒するシートの⽅を、より慎重に扱っています。
  12. 3 ATS API の型 ATSのAPIの型を定義する type AtsStep = | 'entry'

    |/ client.ts:2xx のとき return text if (code >= 200 |& code < 300) { return text ? (JSON.parse(text) as T) : ({} as T); | 'casualInterview' | 'resumeScreening' } | 'firstInterview' // ほか選考ステップ interface AtsCandidacy { id: string; name: string; step: AtsStep; status: 'active' | 'terminated'; requisitionId: string; } ATS の仕様が変わったときに直す場所を、types.ts と キャスト1か所に集約しています
  13. 3 マッピングシートの型 シートの値は unknown で受けて、1セルずつ変換する 有効‧無効状態の扱いなどで使う boolean への変換の例 function parseBool(v:

    unknown): boolean { if (typeof v === 'boolean') return v; const s = String(v || '') .trim() .toUpperCase(); return s === 'TRUE' || s === '1' || s === 'YES'; } 実際に⼊り得る値 チェックボックスの true ⼿⼊⼒の "TRUE" "yes" 末尾の空⽩ 空セル getValues() は any[][] を返すので、any のまま使わずに unknown として扱っています。 まず boolean ならそのまま返す。 それ以外は⽂字列にして、空⽩を取って⼤⽂字にそろえてから判定する、という形で、1セルずつ吸収しています。 他の列も同じように、列ごとに変換を⽤意しています。
  14. 4 エラーハンドリング 失敗したら Slack に通知→スプレッドシート上で対応。 Step 1 評価依頼が失敗 (3回までリトライ) Step

    2 ➞ ログシートに記録 Step 3 ➞ Slack に通知 Step 4 ➞ あくまで「監視と対応はシンプルに」、をコンセプトとしています。 (もちろん原因調査などは必要ですが、エンジニア以外でもパッと対応できることを重視。) ⼈が依頼を送り直す
  15. 4 エラーハンドリング リトライは、スプレッドシートから実⾏できるように ファイル 編集 表⽰ auto-assign ⽇時 候補者ID 結果失敗した⾏を再実⾏

    エラー 10:00 A-1021 done dryRun で確認 10:00 A-1022 failed 11:00 A-1023 done 11:00 A-1024 skipped 12:00 A-1025 pending エンジニアでなくても リトライできる メニューから再実⾏するだけ 429 Too Many Requests status-not-active 状態が⾒える ※ ログシートのイメージ 何が成功して、何が失敗したかを いつものシートで 確認できる
  16. 4 GAS の制限 GAS の制限も意識する 例えば、実⾏時間は6分までしか許されない制限があるので設計にはちょっとした⼯夫を⼊れています。 01 02 取得する量を減らす 途中で⽌まる前提で処理

    ATS 側で対象の求⼈に 絞ってから取得する auto-assign は ATSの選考ステータスや処理状況 (done, pending,failed) を⾒て、次の回が残りを処 理する作りへ。 ※ リトライ回数の上限を超えたら failed にして Slack に通知し、そこからは⼈が調査‧対応へ。
  17. 5 その他のツールの紹介 普段のオペレーションを変えずに複数業務へ適⽤ タスク集約ツール 面談・面接フィードバック Bot 候補者の重複チェック Slack で来る依頼を1件ずつ 確認しな

    くて済むようにした ⾯談‧⾯接の記録と、 LLM による フィードバック 選考にすでに進んでいただいている ⽅ひスカウトを送らないようにする アウトプットする先 アウトプットする先 アウトプットする先 朝会で⾒る Confluence • ATS への連携 スプレッドシートの中で操作が完結 • ドキュメントツールへの ⾃動書き込み • Slack を通じた ⾯接担当者本⼈への フィードバック オペレーションを⼤きく変えず、普段の動きのまま使えるようにして、スムーズに現場に溶け込ませています。
  18. 5 使われるコツ ファーストステップでは、 今までの業務を⼤きく変えすぎない First step Next 今の⼿作業を、 そのまま⾃動化する 業務そのものを⾒直す

    ➞ 画⾯も⼿順も変えないので、 使う⼈が迷わない その業務が本当に必要か、ステップを組み替えられない か含めて考えていく。
  19. 6 書類選考⾃動アサインリリースの効果 2026/6⽉上旬のリリースから約4か⽉で… ⾃動アサインした件数 567 件 減った作業時間 約 19 時間

    1件2分として計算 書類選考のリードタイムも平均12時間→5時間へ短縮 定性⾯) 上記に加えて⼈のスイッチングコストが低下。 Slack への投稿や書類選考の⼊⼒の追いかけがなくなり、本来やりたかった「⼈に向き合う時間」に集中できることに。
  20. 6 まとめ 役に⽴ったのは、エンジニアとして普段からやっていた判断 01 02 03 全社の仕組みに乗せる ⼊⼝に型をつける 仕組みを溶け込ませる 実⾏は

    Workspace、コードは GitHub orgで管理、 専⽤の環境は作らず多くの⼈が運⽤ 可能な状態を作る。 誰が作ったデータを、誰が読むか で、 どこまで厳しくするかを決める て安全に運⽤する。 普段の業務に溶け込ませ、『気づい たら使っている』状態にする。失敗 しても、いつものシートで対応でき るようにする。