Slide 1

Slide 1 text

プロダクト開発でも使おう 関数のオーバーロード Yo Iwamoto プロダクトエンジニア @SmartHR 2025.06.6 TSKaigi 2025 事後勉強会 LT

Slide 2

Slide 2 text

Yo Iwamoto / 岩元 陽 自己紹介 ❏ SmartHR で勤怠管理機能を作っています ❏ 近況: Switch 2 って本当に当たるんですか? @yoiwamoto

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

話したいこと 1. 関数のオーバーロードについて 2. プロダクト開発で役に立った話 3. オーバーロードの性質と使いどころ

Slide 5

Slide 5 text

Function Overloads

Slide 6

Slide 6 text

関数のオーバーロード (Function Overload) https://www.typescriptlang.org/docs/handbook/2/functions.html#overload-signatures-and-the-implementation-signature 関数宣言を複数記述するような形式で関数のシグネチャを列挙し、 パターンマッチにより動的にシグネチャを決定させるような機能。

Slide 7

Slide 7 text

関数のオーバーロード (Function Overload) e.g. react-hook-form の watch() にキー、キーの配列、コールバックが渡せたりするあれ

Slide 8

Slide 8 text

❏ ライブラリとかでよく使われててなんか便利 ❏ 便利だけど、まあメタプロの類 プロダクト開発で使うかと言われるとあんまり? なイメージ。

Slide 9

Slide 9 text

うまく使うと実装がとても簡潔になったり 最強関数(いい意味)を作れる素敵な機能なので、 改めて概要 & 使い所を紹介します!

Slide 10

Slide 10 text

オーバーロードのモチベーション 特に型を工夫しない場合 🤔 引数が string なら string、 number なら number を返すような関数 → 実際に渡した引数の型から動的に推論さ せることができず、常に `number | string`

Slide 11

Slide 11 text

Generics で対応してみる 💭 value を T と置いて、返り値型を分岐する (改行の問題ももちろんあるけど、) - 一定、実装が複雑になる。 - as T extends number ? number : string のような as の使用が避けられない オーバーロードのモチベーション

Slide 12

Slide 12 text

オーバーロードで解決 ✨ 宣言された順の優先度でパターンマッチでシグ ネチャを特定。 実装も型定義もとてもシンプル オーバーロードのモチベーション

Slide 13

Slide 13 text

要するに、 単一の宣言だと限界がある関数シグネチャを、 分割して宣言することによって容易に表現するめの機能 であって、場合によって単に関数を分割したり、Conditional Type を工夫した り、引数のみの分岐であれば Discriminated Union で表現するなど、 基本的に他の方法が取れる。 → より簡潔な型表現にする / ユーティリティ関数のカバーする ユースケースを増やして便利にするために使う

Slide 14

Slide 14 text

最近オーバーロードが 役に立った話

Slide 15

Slide 15 text

作りたかったもの routes 定義のヘルパ。 パスパターンを literal で渡すだけで、必要なパラメータを受け取る path() 関数を返してほしい (こういうものを自前で作ってる経緯は割愛)

Slide 16

Slide 16 text

実現方法 ざっくりこんな感じで実現できる。 ポイントを分解すると、 ① Template Literal Types ② infer による literal からの型の抽出 ③ 関数のオーバーロード キモは、パスパラメータを含まないパター ンの route では、引数を渡さなくてもエ ラーにならないこと

Slide 17

Slide 17 text

よくある使い方 ...は省略

Slide 18

Slide 18 text

一般化すると

Slide 19

Slide 19 text

① 引数型を分岐したい場合 → Union がハマらなければ使う! ② 返り値型などを分岐したい場合 → 以下の場合を除いてまず使ってみる! 関数のオーバーロードの使いどき ➢ 同じ関数でカバーできるメリットがないかも ➢ Template Literal Types などでパターン量が爆発するかも

Slide 20

Slide 20 text

引数にパターンがあるだけであれば、理論上ただの Union でほぼ表現できる。 が、Positional Argument の構造が分岐できない! ⚠ 使いどき ① 引数型を分岐したい場合 公式のサンプルコードでは Positional Argument の構造が分岐していて、 makeDate(1749198911) とも呼べるし、 makeDate(6, 6, 2025) とも呼べる

Slide 21

Slide 21 text

これは Union の場合、以下のようにオブジェクト形式にする、あるいは第二引数を optional にするなどでしか実現できない。 使いどき ① 引数型を分岐したい場合

Slide 22

Slide 22 text

最初の例で言うと、 PathParameter が `{}` であるような場合に第一引数を required にしたり optional にしたりできているのはオーバーロードのおかげ。 使いどき ① 引数型を分岐したい場合

Slide 23

Slide 23 text

使いどき ② 返り値型などを分岐したい場合 基本的には使える が、なんでもありのオーバーロードは正直全く関係のない関数もまとめられるもので、 (理論上は)アプリケーションの全ての関数を 1つでカバーできたりする 秩序を保つために、以下は考える - 同じ関数であるメリットがあるか? - Template Literal Types などでパターン数が爆発しないか? - 推論の度に動的にパターンマッチが実行される - 極端にパターンの多い計算を含んでいると、通常の関数定義より負荷がかかる

Slide 24

Slide 24 text

おわり