What is a Service in Effect?
mainA Service is a contract that defines an interface for a specific capability without providing an implementation. In Effect, services are defined using Context.Service as classes. This allows you to write business logic that depends on these interfaces, ensuring your code is decoupled from specific implementations (like a real database vs. a mock database).
Key Rules for Services:
- Unique Identifiers: Every service must have a unique tag identifier (e.g.,
@app/Database). It is recommended to use a prefix pattern like@path/to/ServiceNameto avoid collisions. - No Method Dependencies: Service methods should not take dependencies as arguments (they should have
R = never). Instead, dependencies are resolved viaLayercomposition. - Immutability: Use
readonlyproperties for service methods to prevent exposing mutable state directly.
import { Effect } from "effect"
import * as Context from "effect/Context"
class Database extends Context.Service<
Database,
{
readonly query: (sql: string) => Effect.Effect<unknown[]>
readonly execute: (sql: string) => Effect.Effect<void>
}
>()("@app/Database") {}