Skip to content
Back to skills

Effect Ts

ASecurity

Expert guide for writing Effect-TS code, including project setup, core principles, data modeling with Schema, error handling, and the Context.Tag service pattern. Use when writing, refactoring, or analyzing TypeScript code using the Effect library.

  • 617 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added June 5, 2026
developmenttypescriptbashtestingrefactoringapidatabase

Works with

  • terminal
  • cli
  • api

Security analysis

A100/100

Pro scans all 20 files and shows the line behind each finding

Scanned June 5, 2026

npx -y skills add pedronauck/skills --skill effect-ts --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Effect Ts?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Effect Ts
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/pedronauck-effect-ts/badge)](https://www.skillsdirectory.com/skills/pedronauck-effect-ts)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: effect-ts
description: Expert guide for writing Effect-TS code, including project setup, core principles, data modeling with Schema, error handling, and the Context.Tag service pattern. Use when writing, refactoring, or analyzing TypeScript code using the Effect library.
allowed-tools: Read, Grep, Glob
---

# Effect-TS Developer Guide

Guidelines, patterns, and best practices for Effect-TS in this project.

## Reference Documents

Read the relevant reference before writing code. `references/core-patterns.md` is the master index.

| Reference | Topics |
|---|---|
| `references/foundations.md` | Setup, imports, TypeScript config |
| `references/construction-and-style.md` | `Effect.gen`, `pipe`, `Effect.fn`, `Effect.fnUntraced` |
| `references/schema-errors-config.md` | Schema modeling, errors, config, retry |
| `references/pattern-matching.md` | **`Match.type`, `Match.value`, `Match.tag`, `Match.exhaustive`** — mandatory for tagged unions |
| `references/control-flow-and-runtime.md` | `Effect.if`, `Effect.when`, loops, `runSync`, `runPromise`, `ManagedRuntime` |
| `references/data-types.md` | **All data types**: `Option`, `Either`, `Data`, `Exit`, `Cause`, `Duration`, `DateTime`, `BigDecimal`, `Chunk`, `HashSet`, `Redacted` |
| `references/data-and-testing.md` | Option/Either/Array quick ref, `@effect/vitest` setup |
| `references/concurrency-and-resources.md` | Concurrency, `Scope`, finalizers, resources |
| `references/streams-deep-dive.md` | Creating, operations, grouping, partitioning, broadcasting, buffering, throttling, error handling |
| `references/sink.md` | Sink constructors, collecting, folding, operations, concurrency, leftovers, `Stream.transduce` |
| `references/batching-and-caching.md` | Request batching (`RequestResolver`), `cachedWithTTL` |
| `references/schema-transforms-and-filters.md` | `Schema.transform`, `Schema.filter`, refinements |
| `references/api-platform-observability.md` | `HttpApi`, logging, tracing, spans |
| `references/class-patterns.md` | `Context.Tag` service pattern, layers, memoization, testing |
| `references/error-handling-patterns.md` | `Data.TaggedError`, `Schema.TaggedError`, error composition, recovery |
| `references/library-development-patterns.md` | Forbidden patterns, `Effect.fn` vs `Effect.fnUntraced`, resource management |
| `references/testing-patterns.md` | `@effect/vitest` with `assert`, `TestClock`, service mocking |
| `references/quality-tooling-and-resources.md` | Anti-patterns, validation checklist, packages |

## Core Principles

1. **Effect is not just for async** — Use `Effect` for any fallible operation
2. **Immutability** — Use Effect's immutable data structures (`Data`, `Chunk`, `HashSet`)
3. **Type Safety** — Track errors in types. No `any` or `unknown` in error channels
4. **Composition** — Build programs by composing small Effects
5. **Schema-First** — Define data models using `Schema` with branded types
6. **Pattern Matching** — Use `Match` for all branching over tagged unions (never `switch`/`if-else` on `_tag`)
7. **Effect Data Types** — Use `Option` (not null), `Either` (not ad-hoc), `Duration` (not raw ms), `DateTime` (not Date), `BigDecimal` (not floats), `Redacted` (for secrets). See `references/data-types.md`

## Quick Reference

### Import Convention

```typescript
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 vs pipe vs Effect.fn

```typescript
// 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);
});
```

### Error Handling

`Data.TaggedError` for in-process discrimination, `Schema.TaggedError` for serializable errors. See `references/error-handling-patterns.md`.

```typescript
export class NotFoundError extends Data.TaggedError("NotFoundError")<{
  id: string;
}> {}

// Recovery
pipe(riskyOp, Effect.catchTag("NotFoundError", (e) => Effect.succeed(null)));
```

### Pattern Matching (Mandatory for Tagged Unions)

**Always use `Match`** — `Match.exhaustive` catches missing cases at compile time. See `references/pattern-matching.md`.

```typescript
// 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}`,
});
```

### Service Pattern (Context.Tag)

See `references/class-patterns.md` for full pattern with factory methods and layers.

```typescript
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) });
  }));
}
```

### Testing

**CRITICAL**: Use `assert` from `@effect/vitest` for `it.effect`. Never `expect` with `it.effect`. See `references/testing-patterns.md`.

```typescript
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))
);
```

## Forbidden Patterns

```typescript
// 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
```

## Validation Checklist

- [ ] Imports use `import * as Module from "effect/Module"`
- [ ] `Effect.gen` for complex logic, `pipe` for linear, `Effect.fn` for public API
- [ ] `Match` for all `_tag` branching with `Match.exhaustive`
- [ ] Branded types for domain primitives (IDs, Emails)
- [ ] Errors: `Data.TaggedError` (discrimination) or `Schema.TaggedError` (serializable)
- [ ] No `any`/`unknown` in error channels, no type assertions
- [ ] No try-catch in `Effect.gen` — use `Effect.exit`
- [ ] `return yield*` for terminal effects (`Effect.fail`, `Effect.interrupt`)
- [ ] Services: `Context.Tag` with static factory methods and `Effect.fn` tracing
- [ ] Layers: `Layer.merge`/`Layer.provide`, parameterized layers in constants
- [ ] Resources: `Effect.acquireRelease` or `Effect.scoped`
- [ ] `Option` for nullable values, `Either` for sync success/failure
- [ ] `Duration` for time values, `DateTime` for dates (not `Date`)
- [ ] `BigDecimal` for financial/precise math, `Redacted` for secrets
- [ ] `Data.struct`/`Data.Class` for structural equality, `HashSet` for sets
- [ ] `Clock.currentTimeMillis` instead of `Date.now()`
- [ ] Tests: `assert` from `@effect/vitest` (not `expect`) with `it.effect`
- [ ] Run `pnpm run typecheck` and `pnpm run test`

## Reference Implementation

See `/packages/looper/src/data/api-client/api-client.ts` for Context.Tag service pattern.

## Effect Solutions CLI

```bash
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
```

Files in this skill

  • SKILL.md9.1 KB
  • references/api-platform-observability.md5.1 KB
  • references/batching-and-caching.md6 KB
  • references/class-patterns.md21.1 KB
  • references/concurrency-and-resources.md4.9 KB
  • references/construction-and-style.md3.4 KB
  • references/control-flow-and-runtime.md6 KB
  • references/core-patterns.md4.1 KB
  • references/data-and-testing.md5.5 KB
  • references/data-types.md21.2 KB
  • references/error-handling-patterns.md12.7 KB
  • references/foundations.md4.1 KB
  • references/library-development-patterns.md10.9 KB
  • references/pattern-matching.md10.5 KB
  • references/quality-tooling-and-resources.md8 KB
  • references/schema-errors-config.md12.6 KB
  • references/schema-transforms-and-filters.md8.6 KB
  • references/sink.md7.4 KB
  • references/streams-deep-dive.md14.7 KB
  • references/testing-patterns.md14.9 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.