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模式时,尤其是中等或高复杂度任务,应主动使用任务工具生成研究代理来查找最佳实践。

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或复杂的依赖注入
  • 处理包含多种错误类型或复杂错误层级的错误处理
  • 基于流的操作和响应式模式
  • 使用作用域效应(scoped effects)和清理逻辑进行资源管理
  • 并发/并行操作和性能关键型代码
  • 测试模式,尤其是不熟悉的测试场景
中等优先级(复杂时需研究):
  • 将命令式代码(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
  • 研究多个相关模式时,生成多个并发的任务代理
  • 专注于寻找规范、可读且可维护的解决方案,而非巧妙的优化
  • 验证建议的方法是否与现有代码库模式一致(如果存在相关模式)
  • 当存在多种实现方式时,研究找到最符合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
  • 使用作用域效应(scoped effects)进行适当的资源管理
  • 使用
    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的失败不会被抛出)
  • 避免: 类型断言(as 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
    快速参考
  • 取消 vs 失败 — 中断不是错误 → 错误分类
  • Option vs 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

创建Effects

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

组合Effects

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)      // 链式调用effects
Effect.map(effect, fn)          // 转换成功值
Effect.tap(effect, fn)          // 执行副作用但不改变值
Effect.all([...effects])        // 运行多个effects(可配置并发)
Effect.forEach(items, fn)       // 遍历项并执行effects

// 收集所有错误(不只是第一个)
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  // 如果缺少case会编译错误
)

// 替换嵌套的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)
// Hook读取: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等

// 在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) }
})

// 自定义配置提供器(例如从对象而非环境变量读取)
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确定性测试模式