Effect

An ecosystem of tools to build robust applications in TypeScript

1 — 概要

Effect は TypeScript アプリの副作用・エラーハンドリング・並行処理を型安全かつ構造的に扱うための関数型エフェクトシステム。pnpm モノレポで管理される 30+ パッケージ群が「core」「platform」「SQL」「AI」など各レイヤーをカバーする。

30+ パッケージ数
TS 5.4+ 必須バージョン
pnpm パッケージマネージャ
strict tsconfig 必須フラグ

従来の try/catchPromise に頼る命令的スタイルを、型で追跡可能な合成可能なエフェクトに置き換えることで「実行時に初めてわかるエラー」をコンパイル時に補足できる。

  • 型安全なエラー追跡: エラー型 E が型シグネチャに現れるため、握りつぶしや未処理エラーがコンパイルで発覚する。
  • 依存注入の型安全化: 要求リソース R も型で表現し、提供しないまま実行しようとするとコンパイルエラーになる。
  • 構造的並行処理: Fiber をファーストクラスで扱い、キャンセル・タイムアウト・リソース解放が自動的かつリーク不可能な形で管理される。
2 — 型シグネチャ
Effect < A E R >
A Success(成功値の型) — エフェクトが成功したときに返す値の型。Effect<string, …> なら成功時に string が得られる。 E Error(期待するエラーの型) — 型で追跡されるビジネスエラー。予期しない例外は別枠(Defect)として分離される。 R Requirements(必要なサービス型) — 実行に必要な依存(Context タグ)のユニオン型。never は依存なしを意味する。
読み方: Effect<User, NotFound | DbError, Database> は「Database サービスが必要で、成功すると User、失敗すると NotFoundDbError を返すエフェクト」。
import { Effect } from "effect"

// 成功値を包む
const greet = Effect.succeed("Hello, Effect!")

// 失敗(型付きエラー)
const fail = Effect.fail(new Error("something went wrong"))

// 同期的な副作用を包む
const now = Effect.sync(() => Date.now())

// エフェクトの連鎖(flatMap / pipe)
const program = Effect.gen(function* () {
  const msg = yield* greet
  const ts  = yield* now
  return `${msg} at ${ts}`
})

// 実行(R = never のエフェクトだけ run できる)
Effect.runPromise(program).then(console.log)
3 — コアモジュール
Effect 副作用・エラーハンドリング・並行処理を構造的に扱うコア抽象。すべての基礎。
Context 型安全な依存注入機構。サービスを直接参照せずに計算へ受け渡す。
Layer 依存関係グラフの宣言的管理。モジュール構成・テスト差し替えに使う。
Fiber 軽量バーチャルスレッド。リソースセーフなキャンセル・並列実行・fork/join を提供。
Stream 非同期・イベント駆動なデータストリームの強力な抽象。バックプレッシャー内蔵。
Schedule リトライ・リピートポリシーを合成可能なスケジュールで定義。指数バックオフ等。
Scope リソースのライフサイクル管理。acquire/release を安全に組み合わせる。
Schema 型安全なデータ定義・バリデーション・変換ライブラリ。encode/decode 両対応。
依存関係: Context → Layer → Scope の順で積み上がり、Effect は全モジュールを統合するランタイムとして機能する。Fiber は Effect の並行処理モデルを実装する低レイヤー。
import { Stream, Effect } from "effect"

// 1 から 10 までを非同期に流す
const numbers = Stream.range(1, 10)

// フィルタ → マップ → fold
const program = Stream.run(
  Stream.pipe(
    numbers,
    Stream.filter(n => n % 2 === 0),
    Stream.map(n => n * n)
  ),
  Sink.collectAll()
)

Effect.runPromise(program).then(console.log)
// [4, 16, 36, 64, 100]
4 — 依存注入(Context / Layer)

Effect の依存注入は Context.Tag(サービス識別子)→ Layer(実装の組み立て)→ Effect.provide(エフェクトへの注入)という 3 ステップで構成される。

Tag 定義 class Database extends Context.Tag("Database")<Database, { query: … }>(){} でサービス識別子を作る
Layer 作成 Layer.effect(Database, Effect.gen(…)) で実装を包んだ Layer を定義する
Layer 合成 Layer.provide(AppLayer, DatabaseLayer) で依存グラフを宣言的に合成
Effect.provide Effect.provide(program, AppLayer) で R が never になり runPromise 可能になる
import { Context, Layer, Effect } from "effect"

// サービスインターフェース
class Database extends Context.Tag("Database")<
  Database,
  { readonly query: (sql: string) => Effect.Effect }
>() {}

// 本番実装
const DatabaseLive = Layer.effect(
  Database,
  Effect.gen(function* () {
    // 実際の DB 接続...
    return { query: (sql) => Effect.tryPromise(() => pg.query(sql)) }
  })
)

// テスト用モック(Layer を差し替えるだけ)
const DatabaseTest = Layer.succeed(Database, {
  query: (_sql) => Effect.succeed([{ id: 1, name: "test" }])
})

const program = Effect.gen(function* () {
  const db = yield* Database
  return yield* db.query("SELECT * FROM users")
})

// テスト
Effect.runPromise(Effect.provide(program, DatabaseTest))
5 — パッケージ一覧
パッケージ説明
effectコアパッケージ。Effect / Context / Layer / Fiber / Stream / Schedule / Scope / Schema を包括
@effect/typeclass関数型プログラミングの型クラス(Functor, Monad 等)
@effect/vitestVitest との統合。Effect を返すテスト関数をネイティブサポート
@effect/experimental実験的 API。安定化前の新機能を先行公開
パッケージ対象ランタイム
@effect/platformクロスプラットフォーム共通抽象(HTTP クライアント・ファイルシステム等)
@effect/platform-nodeNode.js 実装
@effect/platform-node-sharedNode.js 共通ユーティリティ
@effect/platform-bunBun 実装
@effect/platform-browserブラウザ実装
パッケージ対応 DB / ライブラリ
@effect/sqlSQL 抽象レイヤー(共通インターフェース)
@effect/sql-pgpostgres.js(PostgreSQL)
@effect/sql-mysql2mysql2(MySQL / MariaDB)
@effect/sql-mssqltedious(SQL Server)
@effect/sql-sqlite-nodebetter-sqlite3(SQLite / Node)
@effect/sql-sqlite-bunbun:sqlite(SQLite / Bun)
@effect/sql-sqlite-wasm@sqlite.org/sqlite-wasm(SQLite / WebAssembly)
@effect/sql-libsql@libsql/client(Turso / libSQL)
@effect/sql-clickhouseClickHouse
@effect/sql-d1Cloudflare D1
@effect/sql-drizzleDrizzle ORM 統合
@effect/sql-kyselyKysely クエリビルダ統合
@effect/sql-sqlite-doCloudflare Durable Objects SQLite
@effect/sql-sqlite-react-nativereact-native-quick-sqlite
パッケージ説明
@effect/aiAI ユーティリティ(モデル非依存の抽象)
@effect/ai-openaiOpenAI 統合
@effect/ai-anthropicAnthropic Claude 統合
@effect/ai-amazon-bedrockAmazon Bedrock 統合
@effect/ai-googleGoogle AI 統合
@effect/cli型安全な CLI ビルダー
@effect/cluster分散コンピューティングツール
@effect/rpc型安全な RPC(リモートプロシージャコール)
@effect/opentelemetryOpenTelemetry トレーシング統合
@effect/workflow耐障害性のある永続ワークフロー
@effect/printer汎用プリンタユーティリティ
@effect/printer-ansiANSI カラー対応プリンタ
6 — クイックスタート
# コアのみ(TypeScript 5.4+, strict: true が必要)
npm install effect

# Node.js プラットフォームも使う場合
npm install effect @effect/platform @effect/platform-node

tsconfig.json の必須設定

{
  "compilerOptions": {
    "strict": true
    // TypeScript 5.4 以上を使用すること
  }
}

モノレポのビルド・テスト・チェックは pnpm 10.4.0+ で統一管理されている。

pnpm install pnpm codegen pnpm check pnpm test pnpm lint pnpm circular
コマンド説明
pnpm codegenパッケージエントリポイントの再生成(構造変更時)
pnpm checkTypeScript コンパイルエラーなしを確認
pnpm test全ユニットテストを実行
pnpm test-types型レベルテスト(tstyche)
pnpm lintコーディングスタイルチェック
pnpm lint-fix自動修正可能な lint エラーを修正
pnpm circular循環 import の検出
pnpm docgenドキュメント生成の確認