先に要点
- Effect-TS は `成功 / 失敗 / 必要な依存』 を型で同時に表す ` Effect<Success, Error, Requirements>』 という中核型を持つ TypeScript の 関数型エコシステム。
- 提供範囲は広い: ` 型付きエラーハンドリング』 `Schema(Zod 競合)』 `Context / DI(依存注入)』 `Retry / Schedule』 `並行 / Fiber』 `Stream』 `Layer によるアプリ構築』 など。`1つのエコシステムで堅牢な TS バックエンド』 を組める。
- 思想は Scala の ZIO をベース。`例外を投げる代わりに型でエラーを表す』 `依存は型レベルで表す』 という関数型バックエンドの設計を TS に移植した形。
- 本命の使い所は ` 堅牢性が重要な TS バックエンド / 複雑な非同期パイプライン / AI ワークフロー』。学習コストは大きいが、`チーム全体で型と信頼性を引き上げたい』 案件で大きな価値を出す。
Effect-TS ってよく聞くけど、結局何をするライブラリ? Promise / async-await でいいんじゃないの? 関数型ってまた難しい話?』 ── 2023 年あたりから TypeScript の関数型コミュニティで急速に存在感を増した Effect-TS は、TS バックエンドの新しい標準』 を目指す野心的なプロジェクトです。
ざっくり言うと、Effect-TS は 成功・失敗・依存をすべて型で表現する Effect 型を中核に、TS で堅牢なバックエンドを書くためのエコシステム』</strong> です。Promise だと失敗の型が伝わらない』 関数の依存を引数で渡し続けるのが辛い』 リトライ / タイムアウト / 並行性を毎回手で書きたくない』 ── こうした TS バックエンド開発の悩みを、体系的に解決する ことを目指しています。
この記事では、2026 年 5 月時点の Effect-TS v3 系をベースに、仕組み・なぜ生まれたか・基本コード・採用判断軸 を整理します。 仕様は活発に変化しているので、最終確認は 公式 を見るのが安全です。
なぜ Effect-TS が生まれたか
`普通の Promise / async-await で何が困るのか』 が分かると、Effect の動機が見えます。
①エラーの型が消える
`Promise<User>』 は `成功した場合 User を返す』 を示すが、失敗時に何が起きるかは型に表れない。`どんなエラーが投げられるか』 を呼び出し側が知る術がない。
② try / catch だらけ
` catch でエラーを潰す or 投げ直す』 が散らばる。`どこでエラーが処理されているか』 が見えにくくなる。
④ リトライ / タイムアウトの手書き
` 失敗したら3回までリトライ、間隔は指数バックオフ』 のような典型処理を、案件ごとに書き直す。`本質的に同じコードが10箇所に散らばる』 状態。
Effect は これらすべてをEffect 型』 のエコシステムで体系的に扱う』 ことを目指したライブラリです。
Effect 型の中核
Effect の世界で最も大事な型が ` Effect<Success, Error, Requirements>』 です。
import { Effect } from 'effect';
// User を取ってくる Effect(成功時 User、失敗時 UserNotFound、依存 Database)
const getUser = (id: string): Effect.Effect<User, UserNotFound, Database> =>
Effect.gen(function* () {
const db = yield* Database;
const user = yield* db.find(id);
return user;
});
3 つの型パラメータ
`Success』 = 成功時の値、`Error』 = 失敗時のエラー、`Requirements』 = 実行に必要な依存。` 何が起きうるか』 が型で完全に表される。
遅延評価
` Effect は値ではなく `これからやることの記述』』。`Effect.runPromise(effect)』 で初めて実行される。`Promise はすぐ動く / Effect は明示するまで動かない』 という違い。
`Effect.gen』
`yield*』 を使った Generator 構文で、`async/await のように Effect を書ける』。`pipe』 メソッドチェインより読みやすい。
合成
`Effect.flatMap』 `Effect.map』 `Effect.zip』 で、Effect どうしを安全に合成できる。`成功時の処理』 `失敗時の処理』 が分離されたまま記述できる。
`実行を遅延し、型で失敗と依存を表現する』 のが、Effect の体験を一言で表す部分です。
何が嬉しいか — 具体例
Promise』 と Effect』 で同じ処理を書き比べると、違いが見えます。
Promise 版
async function getUser(id: string): Promise<User> {
const db = getDatabase(); // 依存はグローバル / 引数のどれかでうやむや
try {
return await db.find(id);
} catch (err) {
// どんなエラーが投げられるかは型に出ない
throw new UserNotFound(id);
}
}
// リトライしたい場合は手書き
async function getUserWithRetry(id: string): Promise<User> {
for (let i = 0; i < 3; i++) {
try { return await getUser(id); }
catch (e) { if (i === 2) throw e; }
}
throw new Error('unreachable');
}
Effect 版
const getUser = (id: string) =>
Effect.gen(function* () {
const db = yield* Database; // 依存は型レベルで明示
return yield* db.find(id); // 失敗時の型も追える
});
// リトライは標準機能
const getUserWithRetry = (id: string) =>
getUser(id).pipe(Effect.retry({ times: 3 }));
依存が型に出る
` Database を必要とすること』 が呼び出し側に型として伝わる。`関数を呼んでみないと依存が分からない』 が消える。
エラーが型に出る
`UserNotFound』 を返しうることが明示される。`どこかで例外が投げられている』 ではなく `この処理は UserNotFound で失敗する可能性がある』 と読める。
標準のリトライ / スケジュール
`Effect.retry』 `Effect.timeout』 `Effect.race』 `Schedule.exponential』 などが標準提供。`毎回手書きしていた処理』 が宣言的に書ける。
合成可能
` Effect は値として渡せる』 ので、関数で受け取り、加工して返すことができる。`高階の処理(`withLogging』 `withTimeout』)』 を再利用しやすい。
`型と合成可能性で堅牢な TS バックエンドを書く』 のが Effect の中心的な価値です。
エコシステムの広がり
Effect-TS は ` Effect 型 + 周辺ライブラリ群』 でひとつのエコシステムを形成しています。
| 機能 | 中身 | 競合 / 関連 |
|---|---|---|
| Effect 型 / Fiber | 中心 API、並行・キャンセル制御も統合 | Promise + RxJS |
| Schema | 型と検証を一体化したスキーマ | Zod / Valibot |
| Context / Layer | 依存注入(DI)とアプリ構築 | InversifyJS / 手書き DI |
| Stream | 非同期ストリーム | RxJS / async iterator |
| Schedule | リトライ / 周期実行 | p-retry / 手書きループ |
| STM | ソフトウェアトランザクショナルメモリ | (独自領域) |
| HTTP | HTTP クライアント / サーバ | node-fetch / Hono |
`1つのライブラリで TS バックエンドの基本ピースを全部カバーする』 のが Effect のスケールです。
いつ Effect-TS を選ぶか
`Effect を入れる価値が出る案件』 を整理します。
向いている
① 中〜大規模 TS バックエンド、② 失敗の種類が多く `どのエラーが起きうるか』 を型で追いたい、③ 複雑な非同期パイプライン(リトライ・並行・タイムアウトが頻出)、④ AI ワークフロー / 外部 API 連携が多い、⑤ 関数型を学習する文化があるチーム。
部分採用も可能
` 全部を Effect で書く』 のではなく、`重要な非同期パイプラインだけ Effect』 という部分採用ができる。tRPC の Procedure 内で Effect を使う、のような構成も。
Zod / Valibot との関係
` Schema(Effect の検証ライブラリ)』 は Zod と直接競合する。`Effect エコシステムに統一したい』 なら Schema、`独立した検証だけ欲しい』 なら Zod、という棲み分け。
`堅牢な TS バックエンドにコミットできるチーム』 で大きく光るタイプの道具です。
ハマりやすいポイント
便利な反面、現場で踏みやすい注意点も整理します。
①学習コスト
` Promise の感覚で Effect を書こうとすると混乱する』。` Effect は値、実行するには runPromise が必要』などのルールに慣れる時間が要る。`数週間〜1ヶ月』 を見ておくと安全。
② 型エラーの読みづらさ
` 高度な型推論』 を使う関係で、型エラーが長く読みにくいことがある。`型シグネチャを明示的に書く』 ことで分かりやすくなる場面が多い。
③ チームの導入合意
` 1人が Effect で書いて、他は Promise』 だと混在して辛い。`チーム全体で採用するか / しないか』 を最初に決める必要がある。
④ パフォーマンス
` 軽量な処理に Effect は重め』。`単純な Promise 呼び出し1個』 を Effect 化するメリットは薄い。`複雑なパイプライン』 ほど Effect が活きる構造。
`良いプログラムを書ける可能性を上げる代わりに、書く側の学習コストを払う』 のが Effect の特徴です。
AI 時代の Effect-TS
AI 連携の文脈で Effect-TS の役割を整理します。
AI ワークフローの型安全
` LLM 呼び出し → 検証 → 再試行 → タイムアウト処理 → 結果統合』 のような複雑なパイプラインで、Effect の `エラー / リトライ / 並行』 機能がそのまま使える。` AI 系コードの落とし穴を構造的に減らす』。
Schema での構造化出力
` AI に Effect Schema に従った JSON を返させる』 ことで、`AI 出力の検証 + 型推論』 を1つの定義で完結。Zod と同じ思想で、Effect エコシステムに統一できる。
Stream で AI レスポンス
` ストリーミング応答を Effect Stream で扱う』 ことで、`遅延・キャンセル・タイムアウト』 を統一的に書ける。
`AI 時代の信頼性の高い TS バックエンド』 を作りたいときに、Effect-TS の価値は高まっています。
Effect-TS に関するよくある質問
Q. Effect-TS と Zod、どちらを選ぶべきですか?
A. 検証だけなら Zod、エコシステム全体を Effect で統一するなら Effect Schema』</strong>。<a href="/articles/what-is-zod-typescript-validation">Zod</a> は単体で完結する手軽さ、Effect Schema はEffect 型と統合される強み』 がそれぞれの長所です。
Q. Effect-TS は本番運用に耐えますか?
A. 耐えます。Effect は Scala の ZIO の TS 版という長年の設計を継承しており、Vercel・Shopify・Microsoft などの一部チームでも採用事例があります。`採用人口は React ほどではない』 ので、コミュニティが大きい React 系ライブラリほどの情報量は期待できない、と認識しておくのが安全です。
Q. Promise から Effect への移行は大変ですか?
A. 概念の学習が中心』</strong>です。書き換え自体はそこまで大変ではないですが、Effect の世界観』 を理解しないと正しく書けません。`小さなコードから順に書き換える』 段階移行が現実的です。
Q. fp-ts との関係は?
A. Effect-TS は fp-ts の後継的な存在』</strong>として位置づけられています。同じ作者陣の一部が関わっていて、fp-ts より統合的でモダンな API』 を提供しています。`新規プロジェクトは Effect』 が2026 年現在の標準的な選び方です。
Q. Node.js / Bun / Deno で動きますか?
A. はい、すべてのランタイムで動きます。Web 標準 API ベースのコードが多く、Bun や Deno、Cloudflare Workers などのエッジランタイムでも問題なく使えます。
Q. 学習にどのくらいかかりますか?
A. 基本概念で 1〜2 週間、実プロジェクトで使いこなすまで 1〜2 ヶ月』</strong>が現実的な感触です。Promise / async-await に慣れている人ほど、最初の戸惑い』 が大きい傾向。`公式チュートリアル + Effect.gen』 から始めて、徐々に Layer / Schema / Stream に広げると進めやすいです。
Q. Effect-TS を学ぶ最短ルートは?
A. ① 公式の Getting Started』 を1セット、② Effect.gen + yield*』 で簡単な処理、③ Effect.retry / Effect.timeout』 で典型処理、④ Context / Layer』 で DI、⑤ Schema』 で検証、の5ステップが王道です。まず Effect.gen を書いて、yield* に慣れる』 のが最初のハードルです。