Skip to content

Default Services

Effect comes equipped with five pre-built services:

type DefaultServices = Clock | ConfigProvider | Console | Random | Tracer

When we employ these services, there’s no need to explicitly provide their implementations. Effect automatically supplies live versions of these services to our effects, sparing us from manual setup.

Example (Using Clock and Console)

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Clock
Clock
,
import Console
Console
} from "effect"
// ┌─── Effect<void, never, never>
// ▼
const
const program: Effect.Effect<void, never, never>
program
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<void, never, never>>, void>(f: (resume: Effect.Adapter) => Generator<YieldWrap<Effect.Effect<void, never, never>>, void, never>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

@example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
const
const now: number
now
= yield*
import Clock
Clock
.
const currentTimeMillis: Effect.Effect<number, never, never>

@since2.0.0

currentTimeMillis
yield*
import Console
Console
.
const log: (...args: ReadonlyArray<any>) => Effect.Effect<void>

@since2.0.0

log
(`Application started at ${new
var Date: DateConstructor
new (value: number | string | Date) => Date (+3 overloads)
Date
(
const now: number
now
)}`)
})

As you can observe, even if our program utilizes both Clock and Console, the Requirements parameter, representing the services required for the effect to execute, remains set to never. Effect takes care of handling these services seamlessly for us.