mcpField
E
effect-ts

effect-ts

github.com/pedronauck開発647256 回インストール1 日前に更新
リポジトリ

effect-ts について

Effect-TS プロジェクト向けの開発ガイドスキルで、コア API、パターン、テスト、ツールの資料を備えています。型安全な Effect、Schema モデリング、パターンマッチ、検証の規約を示します。

主な機能

  1. 01トピック別リファレンス文書
  2. 02Effect 合成とデータ型の指針
  3. 03網羅性を検査するタグ付きユニオンのマッチ
  4. 04エラーとリソース管理のパターン
  5. 05テストと検証のチェックリスト

活用シーン

  1. 01一貫した規約での Effect-TS 機能実装
  2. 02型付き Schema とエラーのモデリング
  3. 03タグ付きユニオン分岐のレビュー
  4. 04テストとプロジェクト検証の準備

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/pedronauck/skills --skill effect-ts

インストール後、Claude Code で/effect-tsを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
api-platform-observability.md
batching-and-caching.md
class-patterns.md
concurrency-and-resources.md
construction-and-style.md
control-flow-and-runtime.md
core-patterns.md
data-and-testing.md
data-types.md
error-handling-patterns.md
foundations.md
library-development-patterns.md
pattern-matching.md
quality-tooling-and-resources.md
schema-errors-config.md
schema-transforms-and-filters.md
sink.md
streams-deep-dive.md
testing-patterns.md

詳細

Effect-TS 開発ガイド

このプロジェクトにおける Effect-TS のガイドライン、パターン、ベストプラクティスです。

リファレンスドキュメント

コードを書く前に、関連するリファレンスを読んでください。references/core-patterns.md がマスターインデックスです。

リファレンストピック
references/foundations.mdセットアップ、インポート、TypeScript の設定
references/construction-and-style.mdEffect.gen、pipe、Effect.fn、Effect.fnUntraced
references/schema-errors-config.mdスキーマモデリング、エラー、設定、リトライ
references/pattern-matching.mdMatch.type、Match.value、Match.tag、Match.exhaustive — タグ付きユニオンでは必須
references/control-flow-and-runtime.mdEffect.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.mdOption/Either/Array のクイックリファレンス、@effect/vitest のセットアップ
references/concurrency-and-resources.md並行処理、Scope、ファイナライザー、リソース
references/streams-deep-dive.md作成、操作、グループ化、パーティショニング、ブロードキャスト、バッファリング、スロットリング、エラー処理
references/sink.mdSink のコンストラクター、収集、畳み込み、操作、並行処理、残余要素、Stream.transduce
references/batching-and-caching.mdリクエストのバッチ処理(RequestResolver)、cachedWithTTL
references/schema-transforms-and-filters.mdSchema.transform、Schema.filter、絞り込み
references/api-platform-observability.mdHttpApi、ロギング、トレーシング、スパン
references/class-patterns.mdContext.Tag サービスパターン、レイヤー、メモ化、テスト
references/error-handling-patterns.mdData.TaggedError、Schema.TaggedError、エラーの合成、リカバリー
references/library-development-patterns.md禁止パターン、Effect.fn と Effect.fnUntraced の使い分け、リソース管理
references/testing-patterns.mdassert を使った @effect/vitest、TestClock、サービスのモック
references/quality-tooling-and-resources.mdアンチパターン、検証チェックリスト、パッケージ

基本原則

  1. Effect は非同期処理だけのものではありません — 失敗する可能性のあるあらゆる操作に Effect を使用します
  2. 不変性 — Effect の不変データ構造(Data、Chunk、HashSet)を使用します
  3. 型安全性 — エラーを型で追跡します。エラーチャネルに any や unknown を使用しません
  4. 合成 — 小さな Effect を合成してプログラムを構築します
  5. スキーマ優先 — ブランド型を使い、Schema でデータモデルを定義します
  6. パターンマッチング — タグ付きユニオンのすべての分岐に Match を使用します(_tag に対する switch/if-else は使用しません)
  7. 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

コメント