effect-ts

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Effect-TS Expert

Effect-TS 专家指南

Expert guidance for functional programming with the Effect library, covering error handling, dependency injection, composability, and testing patterns.
为使用Effect库进行函数式编程提供专家指导,涵盖错误处理、依赖注入、可组合性和测试模式。

Prerequisites Check

前置检查

Before starting any Effect-related work, verify the Effect-TS source code exists at
~/.effect
.
If missing, stop immediately and inform the user. Clone it before proceeding:
bash
git clone https://github.com/Effect-TS/effect.git ~/.effect
在开始任何与Effect相关的工作之前,请验证Effect-TS源代码是否存在于
~/.effect
路径下。
如果缺失,请立即停止并告知用户。 先克隆代码再继续:
bash
git clone https://github.com/Effect-TS/effect.git ~/.effect

Research Strategy

研究策略

Effect-TS has many ways to accomplish the same task. Proactively research best practices using the Task tool to spawn research agents when working with Effect patterns, especially for moderate to high complexity tasks.
Effect-TS实现同一任务有多种方式。在处理Effect模式时,尤其是中等或高复杂度任务,应主动使用Task工具生成研究代理来调研最佳实践。

Research Sources (Priority Order)

研究资源(优先级排序)

  1. Codebase Patterns First — Examine similar patterns in the current project before implementing. If Effect patterns exist in the codebase, follow them for consistency. If no patterns exist, skip this step.
  2. Effect Source Code — For complex type errors, unclear behavior, or implementation details, examine the Effect source at
    ~/.effect/packages/effect/src/
    . This contains the core Effect logic and modules.
  1. 优先参考代码库现有模式 — 实现前先检查当前项目中的类似模式。如果代码库中已有Effect模式,为保持一致性请遵循这些模式。如果没有相关模式,跳过此步骤。
  2. Effect源代码 — 遇到复杂类型错误、行为不明确或实现细节问题时,查看
    ~/.effect/packages/effect/src/
    路径下的Effect源代码,其中包含核心Effect逻辑和模块。

When to Research

研究触发场景

HIGH Priority (Always Research):
  • Implementing Services, Layers, or complex dependency injection
  • Error handling with multiple error types or complex error hierarchies
  • Stream-based operations and reactive patterns
  • Resource management with scoped effects and cleanup
  • Concurrent/parallel operations and performance-critical code
  • Testing patterns, especially unfamiliar test scenarios
MEDIUM Priority (Research if Complex):
  • Refactoring imperative code (try-catch, promises) to Effect patterns
  • Adding new service dependencies or restructuring service layers
  • Custom error types or extending existing error hierarchies
  • Integrations with external systems (databases, APIs, third-party services)
高优先级(必须调研):
  • 实现Services、Layers或复杂依赖注入
  • 涉及多种错误类型或复杂错误层级的错误处理
  • 基于流的操作和响应式模式
  • 使用作用域效应和清理的资源管理
  • 并发/并行操作和性能关键型代码
  • 测试模式,尤其是不熟悉的测试场景
中优先级(复杂场景下调研):
  • 将命令式代码(try-catch、promises)重构为Effect模式
  • 添加新的服务依赖或重构服务层级
  • 自定义错误类型或扩展现有错误层级
  • 与外部系统(数据库、API、第三方服务)的集成

Research Approach

研究方法

  • Spawn multiple concurrent Task agents when investigating multiple related patterns
  • Focus on finding canonical, readable, and maintainable solutions rather than clever optimizations
  • Verify suggested approaches against existing codebase patterns for consistency (if patterns exist)
  • When multiple approaches are possible, research to find the most idiomatic Effect-TS solution
  • 调研多个相关模式时,生成多个并发的Task代理
  • 专注于寻找规范、可读且可维护的解决方案,而非巧妙的优化
  • 验证建议的方案是否与现有代码库模式一致(如果存在模式)
  • 当有多种实现方式时,调研找出最符合Effect-TS风格的解决方案

Codebase Pattern Discovery

代码库模式发现

When working in a project that uses Effect, check for existing patterns before implementing new code:
  1. Search for Effect imports — Look for files importing from
    'effect'
    to understand existing usage
  2. Identify service patterns — Find how Services and Layers are structured in the project
  3. Note error handling conventions — Check how errors are defined and propagated
  4. Examine test patterns — Look at how Effect code is tested in the project
If no Effect patterns exist in the codebase, proceed using canonical patterns from the Effect source and examples. Do not block on missing codebase patterns.
在使用Effect的项目中工作时,实现新代码前先检查现有模式:
  1. 搜索Effect导入语句 — 查找导入自
    'effect'
    的文件,了解现有使用方式
  2. 识别服务模式 — 找出项目中Services和Layers的结构
  3. 记录错误处理约定 — 查看错误的定义和传播方式
  4. 检查测试模式 — 查看项目中Effect代码的测试方式
如果代码库中没有Effect模式,请使用Effect源代码和示例中的规范模式。不要因缺少代码库模式而停滞。

Effect Principles

Effect核心原则

Apply these core principles when writing Effect code:
编写Effect代码时请遵循以下核心原则:

Error Handling

错误处理

  • Use Effect's typed error system instead of throwing exceptions
  • Define descriptive error types with proper error propagation
  • Use
    Effect.fail
    ,
    Effect.catchTag
    ,
    Effect.catchAll
    for error control flow
  • See
    ./references/CRITICAL_RULES.md
    for forbidden patterns
  • 使用Effect的类型化错误系统,而非抛出异常
  • 定义描述性的错误类型并正确传播
  • 使用
    Effect.fail
    Effect.catchTag
    Effect.catchAll
    控制错误流
  • 查看
    ./references/CRITICAL_RULES.md
    了解禁用模式

Dependency Injection

依赖注入

  • Implement dependency injection using Services and Layers
  • Define services with
    Context.Tag
  • Compose layers with
    Layer.merge
    ,
    Layer.provide
  • Use
    Effect.provide
    to inject dependencies
  • 使用Services和Layers实现依赖注入
  • 使用
    Context.Tag
    定义服务
  • 使用
    Layer.merge
    Layer.provide
    组合层级
  • 使用
    Effect.provide
    注入依赖

Composability

可组合性

  • Leverage Effect's composability for complex operations
  • Use appropriate constructors:
    Effect.succeed
    ,
    Effect.fail
    ,
    Effect.tryPromise
    ,
    Effect.try
  • Apply proper resource management with scoped effects
  • Chain operations with
    Effect.flatMap
    ,
    Effect.map
    ,
    Effect.tap
  • 利用Effect的可组合性处理复杂操作
  • 使用合适的构造函数:
    Effect.succeed
    Effect.fail
    Effect.tryPromise
    Effect.try
  • 使用作用域效应实现正确的资源管理
  • 使用
    Effect.flatMap
    Effect.map
    Effect.tap
    链式调用操作

Code Quality

代码质量

  • Write type-safe code that leverages Effect's type system
  • Use
    Effect.gen
    for readable sequential code
  • Implement proper testing patterns using Effect's testing utilities
  • Prefer
    Effect.fn()
    for automatic telemetry and better stack traces
  • 编写利用Effect类型系统的类型安全代码
  • 使用
    Effect.gen
    编写可读的顺序代码
  • 使用Effect的测试工具实现正确的测试模式
  • 优先使用
    Effect.fn()
    以获得自动遥测和更清晰的堆栈跟踪

Critical Rules

关键规则

Read and internalize
./references/CRITICAL_RULES.md
before writing any Effect code. Key guidelines:
  • INEFFECTIVE: try-catch in Effect.gen (Effect failures aren't thrown)
  • AVOID: Type assertions (as never/any/unknown)
  • RECOMMENDED:
    return yield*
    pattern for errors (makes termination explicit)
编写任何Effect代码前,请阅读并理解
./references/CRITICAL_RULES.md
。核心指南:
  • 不推荐: 在Effect.gen中使用try-catch(Effect的失败不会被抛出)
  • 避免: 类型断言(如never/any/unknown)
  • 推荐: 使用
    return yield*
    模式处理错误(使终止逻辑显式化)

Common Failure Modes

常见失败模式

Quick links to patterns that frequently cause issues:
  • SubscriptionRef version mismatch
    unsafeMake is not a function
    Quick Reference
  • Cancellation vs Failure — Interrupts aren't errors → Error Taxonomy
  • Option vs null — Use Option internally, null at boundaries → OPTION_NULL.md
  • Stream backpressure — Infinite streams hang → STREAMS.md
快速链接到经常引发问题的模式:
  • SubscriptionRef版本不兼容
    unsafeMake is not a function
    快速参考
  • 取消与失败的区别 — 中断不属于错误 → 错误分类
  • Option与null的选择 — 内部使用Option,边界处使用null → OPTION_NULL.md
  • 流背压 — 无限流导致挂起 → STREAMS.md

Explaining Solutions

解决方案说明

When providing solutions, explain the Effect-TS concepts being used and why they're appropriate for the specific use case. If encountering patterns not covered in the documentation, suggest improvements while maintaining consistency with existing codebase patterns (when they exist).
提供解决方案时,请解释所使用的Effect-TS概念,以及为何它们适用于特定场景。如果遇到文档未涵盖的模式,在保持与现有代码库模式一致的前提下(如果存在),建议改进方案。

Quick Reference

快速参考

Creating Effects

创建Effect

typescript
Effect.succeed(value)           // Wrap success value
Effect.fail(error)              // Create failed effect
Effect.tryPromise(fn)           // Wrap promise-returning function
Effect.try(fn)                  // Wrap synchronous throwing function
Effect.sync(fn)                 // Wrap synchronous non-throwing function
typescript
Effect.succeed(value)           // 包装成功值
Effect.fail(error)              // 创建失败的effect
Effect.tryPromise(fn)           // 包装返回Promise的函数
Effect.try(fn)                  // 包装同步抛出异常的函数
Effect.sync(fn)                 // 包装同步不抛出异常的函数

Composing Effects

组合Effect

typescript
Effect.flatMap(effect, fn)      // Chain effects
Effect.map(effect, fn)          // Transform success value
Effect.tap(effect, fn)          // Side effect without changing value
Effect.all([...effects])        // Run effects (concurrency configurable)
Effect.forEach(items, fn)       // Map over items with effects

// Collect ALL errors (not just first)
Effect.all([e1, e2, e3], { mode: "validate" })  // Returns all failures

// Partial success handling
Effect.partition([e1, e2, e3])  // Returns [failures, successes]
typescript
Effect.flatMap(effect, fn)      // 链式调用effect
Effect.map(effect, fn)          // 转换成功值
Effect.tap(effect, fn)          // 执行副作用但不改变值
Effect.all([...effects])        // 运行多个effect(可配置并发)
Effect.forEach(items, fn)       // 遍历项并执行effect

// 收集所有错误(不只是第一个)
Effect.all([e1, e2, e3], { mode: "validate" })  // 返回所有失败结果

// 部分成功处理
Effect.partition([e1, e2, e3])  // 返回[失败结果, 成功结果]

Error Handling

错误处理

typescript
// Define typed errors with Data.TaggedError (preferred)
class UserNotFoundError extends Data.TaggedError("UserNotFoundError")<{
  userId: string
}> {}

// Direct yield of errors (no Effect.fail wrapper needed)
Effect.gen(function* () {
  if (!user) {
    return yield* new UserNotFoundError({ userId })
  }
})

Effect.catchTag(effect, tag, fn) // Handle specific error tag
Effect.catchAll(effect, fn)      // Handle all errors
Effect.result(effect)            // Convert to Exit value
Effect.orElse(effect, alt)       // Fallback effect
typescript
// 推荐使用Data.TaggedError定义类型化错误
class UserNotFoundError extends Data.TaggedError("UserNotFoundError")<{
  userId: string
}> {}

// 直接yield错误(无需Effect.fail包装)
Effect.gen(function* () {
  if (!user) {
    return yield* new UserNotFoundError({ userId })
  }
})

Effect.catchTag(effect, tag, fn) // 处理特定标签的错误
Effect.catchAll(effect, fn)      // 处理所有错误
Effect.result(effect)            // 转换为Exit值
Effect.orElse(effect, alt)       // 备选effect

Error Taxonomy

错误分类

Categorize errors for appropriate handling:
CategoryExamplesHandling
Expected RejectionsUser cancel, denyGraceful exit, no retry
Domain ErrorsValidation, business rulesShow to user, don't retry
DefectsBugs, assertionsLog + alert, investigate
InterruptionsFiber cancel, timeoutCleanup, may retry
Unknown/ForeignThrown exceptionsNormalize at boundary
typescript
// Pattern: Normalize unknown errors at boundary
const safeBoundary = Effect.catchAllDefect(effect, (defect) =>
  Effect.fail(new UnknownError({ cause: defect }))
)

// Pattern: Catch user-initiated cancellations separately
Effect.catchTag(effect, "UserCancelledError", () => Effect.succeed(null))

// Pattern: Handle interruptions differently from failures
Effect.onInterrupt(effect, () => Effect.log("Operation cancelled"))
对错误进行分类以采取适当的处理方式:
分类示例处理方式
预期拒绝用户取消、拒绝优雅退出,不重试
领域错误验证错误、业务规则展示给用户,不重试
缺陷漏洞、断言失败记录并告警,调查原因
中断Fiber取消、超时清理资源,可重试
未知/外部错误抛出的异常在边界处标准化
typescript
// 模式:在边界处标准化未知错误
const safeBoundary = Effect.catchAllDefect(effect, (defect) =>
  Effect.fail(new UnknownError({ cause: defect }))
)

// 模式:单独捕获用户发起的取消操作
Effect.catchTag(effect, "UserCancelledError", () => Effect.succeed(null))

// 模式:区别处理中断和失败
Effect.onInterrupt(effect, () => Effect.log("操作已取消"))

Pattern Matching (Match Module)

模式匹配(Match模块)

Default branching tool for tagged unions and complex conditionals.
typescript
import { Match } from "effect"

// Type-safe exhaustive matching on tagged errors
const handleError = Match.type<AppError>().pipe(
  Match.tag("UserCancelledError", () => null),          // Expected rejection
  Match.tag("ValidationError", (e) => e.message),       // Domain error
  Match.tag("NetworkError", () => "Connection failed"), // Retryable
  Match.exhaustive  // Compile error if case missing
)

// Replace nested catchTag chains
// BEFORE: effect.pipe(catchTag("A", ...), catchTag("B", ...), catchTag("C", ...))
// AFTER:
Effect.catchAll(effect, (error) =>
  Match.value(error).pipe(
    Match.tag("A", handleA),
    Match.tag("B", handleB),
    Match.tag("C", handleC),
    Match.exhaustive
  )
)

// Match on values (cleaner than if/else)
const describe = Match.value(status).pipe(
  Match.when("pending", () => "Loading..."),
  Match.when("success", () => "Done!"),
  Match.orElse(() => "Unknown")
)
处理标签联合类型和复杂条件的默认分支工具。
typescript
import { Match } from "effect"

// 对标签错误进行类型安全的穷尽匹配
const handleError = Match.type<AppError>().pipe(
  Match.tag("UserCancelledError", () => null),          // 预期拒绝
  Match.tag("ValidationError", (e) => e.message),       // 领域错误
  Match.tag("NetworkError", () => "连接失败"), // 可重试
  Match.exhaustive  // 如果缺少分支会触发编译错误
)

// 替换嵌套的catchTag链
// 之前:effect.pipe(catchTag("A", ...), catchTag("B", ...), catchTag("C", ...))
// 之后:
Effect.catchAll(effect, (error) =>
  Match.value(error).pipe(
    Match.tag("A", handleA),
    Match.tag("B", handleB),
    Match.tag("C", handleC),
    Match.exhaustive
  )
)

// 对值进行匹配(比if/else更简洁)
const describe = Match.value(status).pipe(
  Match.when("pending", () => "加载中..."),
  Match.when("success", () => "完成!"),
  Match.orElse(() => "未知状态")
)

Services and Layers

服务与层级

typescript
// Pattern 1: Context.Tag (implementation provided separately via Layer)
class MyService extends Context.Tag("MyService")<MyService, { ... }>() {}
const MyServiceLive = Layer.succeed(MyService, { ... })
Effect.provide(effect, MyServiceLive)

// Pattern 2: Effect.Service (default implementation bundled)
class UserRepo extends Effect.Service<UserRepo>()("UserRepo", {
  effect: Effect.gen(function* () {
    const db = yield* Database
    return { findAll: db.query("SELECT * FROM users") }
  }),
  dependencies: [Database.Default],  // Optional service dependencies
  accessors: true                     // Auto-generate method accessors
}) {}
Effect.provide(effect, UserRepo.Default)  // .Default layer auto-generated
// Use UserRepo.DefaultWithoutDependencies when deps provided separately

// Effect.Service with parameters (3.16.0+)
class ConfiguredApi extends Effect.Service<ConfiguredApi>()("ConfiguredApi", {
  effect: (config: { baseUrl: string }) =>
    Effect.succeed({ fetch: (path: string) => `${config.baseUrl}/${path}` })
}) {}

// Pattern 3: Context.Reference (defaultable tags - 3.11.0+)
class SpecialNumber extends Context.Reference<SpecialNumber>()(
  "SpecialNumber",
  { defaultValue: () => 2048 }
) {}
// No Layer required if default value suffices

// Pattern 4: Context.ReadonlyTag (covariant - 3.18.0+)
// Use for functions that consume services without modifying the type
function effectHandler<I, A, E, R>(service: Context.ReadonlyTag<I, Effect.Effect<A, E, R>>) {
  // Handler can use service in a covariant position
}
typescript
// 模式1:Context.Tag(实现通过Layer单独提供)
class MyService extends Context.Tag("MyService")<MyService, { ... }>() {}
const MyServiceLive = Layer.succeed(MyService, { ... })
Effect.provide(effect, MyServiceLive)

// 模式2:Effect.Service(捆绑默认实现)
class UserRepo extends Effect.Service<UserRepo>()("UserRepo", {
  effect: Effect.gen(function* () {
    const db = yield* Database
    return { findAll: db.query("SELECT * FROM users") }
  }),
  dependencies: [Database.Default],  // 可选的服务依赖
  accessors: true                     // 自动生成方法访问器
}) {}
Effect.provide(effect, UserRepo.Default)  // .Default层级自动生成
// 当依赖单独提供时,使用UserRepo.DefaultWithoutDependencies

// 带参数的Effect.Service(3.16.0+)
class ConfiguredApi extends Effect.Service<ConfiguredApi>()("ConfiguredApi", {
  effect: (config: { baseUrl: string }) =>
    Effect.succeed({ fetch: (path: string) => `${config.baseUrl}/${path}` })
}) {}

// 模式3:Context.Reference(可默认的标签 - 3.11.0+)
class SpecialNumber extends Context.Reference<SpecialNumber>()(
  "SpecialNumber",
  { defaultValue: () => 2048 }
) {}
// 如果默认值足够,无需Layer

// 模式4:Context.ReadonlyTag(协变 - 3.18.0+)
// 用于消费服务但不修改类型的函数
function effectHandler<I, A, E, R>(service: Context.ReadonlyTag<I, Effect.Effect<A, E, R>>) {
  // 处理器可以在协变位置使用服务
}

Generator Pattern

生成器模式

typescript
Effect.gen(function* () {
  const a = yield* effectA;
  const b = yield* effectB;
  if (error) {
    return yield* Effect.fail(new MyError());
  }
  return result;
});

// Effect.fn - automatic tracing and telemetry (preferred for named functions)
const fetchUser = Effect.fn("fetchUser")(function* (id: string) {
  const db = yield* Database
  return yield* db.query(id)
})
// Creates spans, captures call sites, provides better stack traces
typescript
Effect.gen(function* () {
  const a = yield* effectA;
  const b = yield* effectB;
  if (error) {
    return yield* Effect.fail(new MyError());
  }
  return result;
});

// Effect.fn - 自动追踪和遥测(命名函数优先使用)
const fetchUser = Effect.fn("fetchUser")(function* (id: string) {
  const db = yield* Database
  return yield* db.query(id)
})
// 创建调用链、捕获调用位置、提供更清晰的堆栈跟踪

Resource Management

资源管理

typescript
Effect.acquireUseRelease(acquire, use, release)  // Bracket pattern
Effect.scoped(effect)                            // Scope lifetime to effect
Effect.addFinalizer(cleanup)                     // Register cleanup action
typescript
Effect.acquireUseRelease(acquire, use, release)  // Bracket模式
Effect.scoped(effect)                            // 将effect的生命周期绑定到作用域
Effect.addFinalizer(cleanup)                     // 注册清理操作

Duration

时长

Effect accepts human-readable duration strings anywhere a
DurationInput
is expected:
typescript
// String syntax (preferred) - singular or plural forms work
Duration.toMillis("5 minutes")    // 300000
Duration.toMillis("1 minute")     // 60000
Duration.toMillis("30 seconds")   // 30000
Duration.toMillis("100 millis")   // 100

// Verbose syntax (avoid)
Duration.toMillis(Duration.minutes(5))  // Same result, more verbose

// Common units: millis, seconds, minutes, hours, days, weeks
// Also: nanos, micros
在任何需要
DurationInput
的地方,Effect接受人类可读的时长字符串:
typescript
// 字符串语法(推荐)- 单数或复数形式均可
Duration.toMillis("5 minutes")    // 300000
Duration.toMillis("1 minute")     // 60000
Duration.toMillis("30 seconds")   // 30000
Duration.toMillis("100 millis")   // 100

// 冗长语法(避免使用)
Duration.toMillis(Duration.minutes(5))  // 结果相同,但更冗长

// 常用单位:millis, seconds, minutes, hours, days, weeks
// 其他单位:nanos, micros

Scheduling

调度

typescript
Effect.retry(effect, Schedule.exponential("100 millis"))  // Retry with backoff
Effect.repeat(effect, Schedule.fixed("1 second"))         // Repeat on schedule
Schedule.compose(s1, s2)                                  // Combine schedules
typescript
Effect.retry(effect, Schedule.exponential("100 millis"))  // 带退避策略的重试
Effect.repeat(effect, Schedule.fixed("1 second"))         // 按调度重复执行
Schedule.compose(s1, s2)                                  // 组合调度策略

State Management

状态管理

typescript
Ref.make(initialValue)       // Mutable reference
Ref.get(ref)                 // Read value
Ref.set(ref, value)          // Write value
Deferred.make<E, A>()        // One-time async value
typescript
Ref.make(initialValue)       // 可变引用
Ref.get(ref)                 // 读取值
Ref.set(ref, value)          // 写入值
Deferred.make<E, A>()        // 一次性异步值

SubscriptionRef (Reactive References)

SubscriptionRef(响应式引用)

typescript
// WARNING: Never use unsafeMake - it may not exist in your Effect version.
// If you see "unsafeMake is not a function", use the safe API below.

SubscriptionRef.make(initial)      // Create reactive reference (safe)
SubscriptionRef.get(ref)           // Read current value
SubscriptionRef.set(ref, value)    // Update value (notifies subscribers)
SubscriptionRef.changes(ref)       // Stream of value changes

// React integration (effect-atom pattern)
const ref = yield* SubscriptionRef.make<User | null>(null)
// Hook reads: useSubscriptionRef(ref) — returns current value or null
// Handle null explicitly in components
typescript
// 警告:永远不要使用unsafeMake - 你的Effect版本中可能不存在该方法。
// 如果看到"unsafeMake is not a function",请使用下面的安全API。

SubscriptionRef.make(initial)      // 创建响应式引用(安全)
SubscriptionRef.get(ref)           // 读取当前值
SubscriptionRef.set(ref, value)    // 更新值(通知订阅者)
SubscriptionRef.changes(ref)       // 值变化的流

// React集成(effect-atom模式)
const ref = yield* SubscriptionRef.make<User | null>(null)
// 钩子读取:useSubscriptionRef(ref) — 返回当前值或null
// 在组件中显式处理null

Concurrency

并发

typescript
Effect.fork(effect)              // Run in background fiber
Fiber.join(fiber)                // Wait for fiber result
Effect.race(effect1, effect2)    // First to complete wins
Effect.all([...effects], { concurrency: "unbounded" })
typescript
Effect.fork(effect)              // 在后台fiber中运行
Fiber.join(fiber)                // 等待fiber结果
Effect.race(effect1, effect2)    // 先完成的获胜
Effect.all([...effects], { concurrency: "unbounded" })

Configuration & Environment Variables

配置与环境变量

typescript
import { Config, ConfigProvider, Effect, Layer, Redacted } from "effect"

// Basic config values
const port = Config.number("PORT")                    // Required number
const host = Config.string("HOST").pipe(              // Optional with default
  Config.withDefault("localhost")
)

// Sensitive values (masked in logs)
const apiKey = Config.redacted("API_KEY")             // Returns Redacted<string>
const secret = Redacted.value(yield* apiKey)          // Unwrap when needed

// Nested configuration with prefix
const dbConfig = Config.all({
  host: Config.string("HOST"),
  port: Config.number("PORT"),
  name: Config.string("NAME"),
}).pipe(Config.nested("DATABASE"))                    // DATABASE_HOST, DATABASE_PORT, etc.

// Using config in effects
const program = Effect.gen(function* () {
  const p = yield* Config.number("PORT")
  const key = yield* Config.redacted("API_KEY")
  return { port: p, apiKey: Redacted.value(key) }
})

// Custom config provider (e.g., from object instead of env)
const customProvider = ConfigProvider.fromMap(
  new Map([["PORT", "3000"], ["API_KEY", "secret"]])
)
const withCustomConfig = Effect.provide(
  program,
  Layer.setConfigProvider(customProvider)
)

// Config validation and transformation
const validPort = Config.number("PORT").pipe(
  Config.validate({
    message: "Port must be between 1 and 65535",
    validation: (n) => n >= 1 && n <= 65535,
  })
)
typescript
import { Config, ConfigProvider, Effect, Layer, Redacted } from "effect"

// 基础配置值
const port = Config.number("PORT")                    // 必填数字
const host = Config.string("HOST").pipe(              // 可选,带默认值
  Config.withDefault("localhost")
)

// 敏感值(日志中会被掩码)
const apiKey = Config.redacted("API_KEY")             // 返回Redacted<string>
const secret = Redacted.value(yield* apiKey)          // 需要时解包

// 带前缀的嵌套配置
const dbConfig = Config.all({
  host: Config.string("HOST"),
  port: Config.number("PORT"),
  name: Config.string("NAME"),
}).pipe(Config.nested("DATABASE"))                    // 对应DATABASE_HOST、DATABASE_PORT等

// 在effect中使用配置
const program = Effect.gen(function* () {
  const p = yield* Config.number("PORT")
  const key = yield* Config.redacted("API_KEY")
  return { port: p, apiKey: Redacted.value(key) }
})

// 自定义配置提供器(例如从对象而非环境变量读取)
const customProvider = ConfigProvider.fromMap(
  new Map([["PORT", "3000"], ["API_KEY", "secret"]])
)
const withCustomConfig = Effect.provide(
  program,
  Layer.setConfigProvider(customProvider)
)

// 配置验证与转换
const validPort = Config.number("PORT").pipe(
  Config.validate({
    message: "端口必须在1到65535之间",
    validation: (n) => n >= 1 && n <= 65535,
  })
)

Array Operations

数组操作

typescript
import { Array as Arr, Order } from "effect"

// Sorting with built-in orderings (accepts any Iterable)
Arr.sort([3, 1, 2], Order.number)              // [1, 2, 3]
Arr.sort(["b", "a", "c"], Order.string)        // ["a", "b", "c"]
Arr.sort(new Set([3n, 1n, 2n]), Order.bigint)  // [1n, 2n, 3n]

// Sort by derived value
Arr.sortWith(users, (u) => u.age, Order.number)

// Sort by multiple criteria
Arr.sortBy(
  users,
  Order.mapInput(Order.number, (u: User) => u.age),
  Order.mapInput(Order.string, (u: User) => u.name)
)

// Built-in orderings: Order.string, Order.number, Order.bigint, Order.boolean, Order.Date
// Reverse ordering: Order.reverse(Order.number)
typescript
import { Array as Arr, Order } from "effect"

// 使用内置排序规则排序(支持任何Iterable)
Arr.sort([3, 1, 2], Order.number)              // [1, 2, 3]
Arr.sort(["b", "a", "c"], Order.string)        // ["a", "b", "c"]
Arr.sort(new Set([3n, 1n, 2n]), Order.bigint)  // [1n, 2n, 3n]

// 根据派生值排序
Arr.sortWith(users, (u) => u.age, Order.number)

// 多条件排序
Arr.sortBy(
  users,
  Order.mapInput(Order.number, (u: User) => u.age),
  Order.mapInput(Order.string, (u: User) => u.name)
)

// 内置排序规则:Order.string, Order.number, Order.bigint, Order.boolean, Order.Date
// 反向排序:Order.reverse(Order.number)

Utility Functions

工具函数

typescript
import { constVoid as noop } from "effect/Function"

// constVoid returns undefined, useful as a no-operation callback
noop()  // undefined

// Common use cases:
Effect.tap(effect, noop)              // Ignore value, just run effect
Promise.catch(noop)                   // Swallow errors
eventEmitter.on("event", noop)        // Register empty handler
typescript
import { constVoid as noop } from "effect/Function"

// constVoid返回undefined,用作无操作回调
noop()  // undefined

// 常见用例:
Effect.tap(effect, noop)              // 忽略值,仅执行effect
Promise.catch(noop)                   // 吞掉错误
eventEmitter.on("event", noop)        // 注册空处理器

Deprecations

废弃说明

  • BigDecimal.fromNumber
    — Use
    BigDecimal.unsafeFromNumber
    instead (3.11.0+)
  • Schema.annotations()
    — Now removes previously set identifier annotations; identifiers are tied to the schema's
    ast
    reference only (3.17.10)
  • BigDecimal.fromNumber
    — 请改用
    BigDecimal.unsafeFromNumber
    (3.11.0+)
  • Schema.annotations()
    — 现在会移除之前设置的标识符注解;标识符仅与schema的
    ast
    引用绑定(3.17.10)

Additional Resources

额外资源

Local Effect Resources

本地Effect资源

  • ~/.effect/packages/effect/src/
    — Core Effect modules and implementation
  • ~/.effect/packages/effect/src/
    — 核心Effect模块与实现

External Resources

外部资源

Reference Files

参考文件

  • ./references/CRITICAL_RULES.md
    — Forbidden patterns and mandatory conventions
  • ./references/EFFECT_ATOM.md
    — Effect-Atom reactive state management for React
  • ./references/NEXT_JS.md
    — Effect + Next.js 15+ App Router integration patterns
  • ./references/OPTION_NULL.md
    — Option vs null boundary patterns
  • ./references/STREAMS.md
    — Stream patterns and backpressure gotchas
  • ./references/TESTING.md
    — Vitest deterministic testing patterns
  • ./references/CRITICAL_RULES.md
    — 禁用模式与强制约定
  • ./references/EFFECT_ATOM.md
    — 用于React的Effect-Atom响应式状态管理
  • ./references/NEXT_JS.md
    — Effect + Next.js 15+ App Router集成模式
  • ./references/OPTION_NULL.md
    — Option与null的边界模式
  • ./references/STREAMS.md
    — 流模式与背压陷阱
  • ./references/TESTING.md
    — Vitest确定性测试模式