effect-ts について
Effect-TS プロジェクト向けの開発ガイドスキルで、コア API、パターン、テスト、ツールの資料を備えています。型安全な Effect、Schema モデリング、パターンマッチ、検証の規約を示します。
主な機能
- 01トピック別リファレンス文書
- 02Effect 合成とデータ型の指針
- 03網羅性を検査するタグ付きユニオンのマッチ
- 04エラーとリソース管理のパターン
- 05テストと検証のチェックリスト
活用シーン
- 01一貫した規約での Effect-TS 機能実装
- 02型付き Schema とエラーのモデリング
- 03タグ付きユニオン分岐のレビュー
- 04テストとプロジェクト検証の準備
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ pedronauck/ skills --skill effect-tsインストール後、Claude Code で/effect-tsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/api-platform-observability.mdbatching-and-caching.mdclass-patterns.mdconcurrency-and-resources.mdconstruction-and-style.mdcontrol-flow-and-runtime.mdcore-patterns.mddata-and-testing.mddata-types.mderror-handling-patterns.mdfoundations.mdlibrary-development-patterns.mdpattern-matching.mdquality-tooling-and-resources.mdschema-errors-config.mdschema-transforms-and-filters.mdsink.mdstreams-deep-dive.mdtesting-patterns.md詳細
Effect-TS 開発ガイド
このプロジェクトにおける Effect-TS のガイドライン、パターン、ベストプラクティスです。
リファレンスドキュメント
コードを書く前に、関連するリファレンスを読んでください。references/core-patterns.md がマスターインデックスです。
| リファレンス | トピック |
|---|---|
references/foundations.md | セットアップ、インポート、TypeScript の設定 |
references/construction-and-style.md | Effect.gen、pipe、Effect.fn、Effect.fnUntraced |
references/schema-errors-config.md | スキーマモデリング、エラー、設定、リトライ |
references/pattern-matching.md | Match.type、Match.value、Match.tag、Match.exhaustive — タグ付きユニオンでは必須 |
references/control-flow-and-runtime.md | Effect.if、Effect.when、ループ、runSync、runPromise、ManagedRuntime |
references/data-types.md | すべてのデータ型:Option、Either、Data、Exit、Cause、Duration、DateTime、BigDecimal、Chunk、HashSet、Redacted |
references/data-and-testing.md | Option/Either/Array のクイックリファレンス、@effect/vitest のセットアップ |
references/concurrency-and-resources.md | 並行処理、Scope、ファイナライザー、リソース |
references/streams-deep-dive.md | 作成、操作、グループ化、パーティショニング、ブロードキャスト、バッファリング、スロットリング、エラー処理 |
references/sink.md | Sink のコンストラクター、収集、畳み込み、操作、並行処理、残余要素、Stream.transduce |
references/batching-and-caching.md | リクエストのバッチ処理(RequestResolver)、cachedWithTTL |
references/schema-transforms-and-filters.md | Schema.transform、Schema.filter、絞り込み |
references/api-platform-observability.md | HttpApi、ロギング、トレーシング、スパン |
references/class-patterns.md | Context.Tag サービスパターン、レイヤー、メモ化、テスト |
references/error-handling-patterns.md | Data.TaggedError、Schema.TaggedError、エラーの合成、リカバリー |
references/library-development-patterns.md | 禁止パターン、Effect.fn と Effect.fnUntraced の使い分け、リソース管理 |
references/testing-patterns.md | assert を使った @effect/vitest、TestClock、サービスのモック |
references/quality-tooling-and-resources.md | アンチパターン、検証チェックリスト、パッケージ |
基本原則
- Effect は非同期処理だけのものではありません — 失敗する可能性のあるあらゆる操作に
Effectを使用します - 不変性 — Effect の不変データ構造(
Data、Chunk、HashSet)を使用します - 型安全性 — エラーを型で追跡します。エラーチャネルに
anyやunknownを使用しません - 合成 — 小さな Effect を合成してプログラムを構築します
- スキーマ優先 — ブランド型を使い、
Schemaでデータモデルを定義します - パターンマッチング — タグ付きユニオンのすべての分岐に
Matchを使用します(_tagに対するswitch/if-elseは使用しません) - Effect のデータ型 —
Option(null の代わり)、Either(場当たり的な実装の代わり)、Duration(生のミリ秒値の代わり)、DateTime(Date の代わり)、BigDecimal(浮動小数点数の代わり)、Redacted(シークレット用)を使用します。references/data-types.mdを参照してください
クイックリファレンス
インポート規約
import * as Context from "effect/Context";
import * as Effect from "effect/Effect";
import * as Layer from "effect/Layer";
import * as Schema from "effect/Schema";
import * as Match from "effect/Match";
import * as Option from "effect/Option";
import * as Either from "effect/Either";
import * as Data from "effect/Data";
import * as Duration from "effect/Duration";
import { pipe } from "effect/Function";
// Also: DateTime, BigDecimal, Chunk, HashSet, Exit, Cause, Redacted
Effect.gen と pipe と Effect.fn
// Effect.gen — complex logic with branching
Effect.gen(function* () {
const user = yield* fetchUser(id);
if (user.isAdmin) yield* logAdminAccess(user);
return user;
});
// pipe — linear transformations
pipe(fetchData(), Effect.map(transform), Effect.flatMap(save));
// Effect.fn — traced reusable functions (public API)
const processUser = Effect.fn("processUser")(function* (userId: string) {
const user = yield* getUser(userId);
return yield* processData(user);
});
エラー処理
プロセス内での判別には Data.TaggedError、シリアライズ可能なエラーには Schema.TaggedError を使用します。references/error-handling-patterns.md を参照してください。
export class NotFoundError extends Data.TaggedError("NotFoundError")<{
id: string;
}> {}
// Recovery
pipe(riskyOp, Effect.catchTag("NotFoundError", (e) => Effect.succeed(null)));
パターンマッチング(タグ付きユニオンでは必須)
常に Match を使用してください — Match.exhaustive により、ケースの不足をコンパイル時に検出できます。references/pattern-matching.md を参照してください。
// Match.type — reusable matcher function
const handle = Match.type<Status>().pipe(
Match.tag("Pending", (s) => `Pending since ${s.requestedAt}`),
Match.tag("Approved", (s) => `Approved by ${s.approvedBy}`),
Match.exhaustive // Compile error if any variant is missing
);
// Match.valueTags — shorthand for immediate matching
Match.valueTags(status, {
Pending: (s) => `Pending since ${s.requestedAt}`,
Approved: (s) => `Approved by ${s.approvedBy}`,
});
サービスパターン(Context.Tag)
ファクトリーメソッドとレイヤーを使ったパターンの詳細は、references/class-patterns.md を参照してください。
export class MyService extends Context.Tag("@myapp/MyService")<
MyService,
{ readonly find: (id: string) => Effect.Effect<Result, NotFoundError> }
>() {
static readonly layer = Layer.effect(MyService, Effect.gen(function* () {
const db = yield* Database;
return MyService.of({ find: MyService.createFind(db) });
}));
}
テスト
重要:it.effect では @effect/vitest の assert を使用してください。it.effect で expect を使用しないでください。references/testing-patterns.md を参照してください。
import { assert, describe, it } from "@effect/vitest";
it.effect("processes data", () =>
Effect.gen(function* () {
const result = yield* processData("input");
assert.strictEqual(result, "expected");
}).pipe(Effect.provide(MyService.testLayer))
);
禁止パターン
// NEVER: try-catch in Effect.gen — use Effect.exit instead
Effect.gen(function* () {
try { yield* someEffect } catch (e) { } // WRONG — will never catch
});
// NEVER: Type assertions
const value = something as any; // FORBIDDEN
const value = something as never; // FORBIDDEN
// NEVER: Missing return on terminal yield
Effect.gen(function* () {
if (bad) { yield* Effect.fail("err") } // Missing return!
});
// NEVER: switch/if-else on _tag — use Match instead
switch (status._tag) { /* no exhaustiveness checking! */ }
// NEVER: Effect.runSync inside Effects
Effect.gen(function* () { Effect.runSync(sideEffect) }); // Loses error tracking
// NEVER: Native JS where Effect data types exist
const x: string | null = null; // Use Option<string>
const delay = 5000; // Use Duration.seconds(5)
const now = new Date(); // Use DateTime.now or DateTime.unsafeNow()
const price = 0.1 + 0.2; // Use BigDecimal for precision
const secret = "sk-1234"; // Use Redacted.make("sk-1234")
// NEVER: expect with it.effect
it.effect("test", () => Effect.gen(function* () {
expect(result).toBe(value) // WRONG — use assert.strictEqual
}));
// NEVER: Inline layers (breaks memoization)
Layer.provide(Postgres.layer({ url })) // Store in constant instead
検証チェックリスト
- インポートには
import * as Module from "effect/Module"を使用します - 複雑なロジックには
Effect.gen、直線的な処理にはpipe、公開 API にはEffect.fnを使用します - すべての
_tagによる分岐には、Match.exhaustiveを指定したMatchを使用します - ドメインプリミティブ(ID、メールアドレス)にはブランド型を使用します
- エラーには
Data.TaggedError(判別用)またはSchema.TaggedError(シリアライズ可能)を使用します - エラーチャネルで
any/unknownを使用せず、型アサーションも使用しません -
Effect.gen内で try-catch を使用せず、Effect.exitを使用します - 終端エフェクト(
Effect.fail、Effect.interrupt)にはreturn yield*を使用します - サービスには、静的ファクトリーメソッドと
Effect.fnによるトレーシングを備えたContext.Tagを使用します - レイヤーには
Layer.merge/Layer.provideを使用し、パラメーター化されたレイヤーは定数にします - リソースには
Effect.acquireReleaseまたはEffect.scopedを使用します - null 許容値には
Option、同期的な成功/失敗にはEitherを使用します - 時間の値には
Duration、日付にはDateではなくDateTimeを使用します - 金融計算/高精度計算には
BigDecimal、シークレットにはRedactedを使用します - 構造的等価性には
Data.struct/Data.Class、集合にはHashSetを使用します -
Date.now()ではなくClock.currentTimeMillisを使用します - テストでは
expectではなく@effect/vitestのassertを使用し、it.effectを使います -
pnpm run typecheckとpnpm run testを実行します
参考実装
Context.Tag サービスのパターンについては、/packages/looper/src/data/api-client/api-client.ts を参照してください。
Effect Solutions CLI
pnpm exec effect-solutions list # List all topics
pnpm exec effect-solutions show <slug...> # Read topics
pnpm exec effect-solutions search <term> # Search by keyword