<Input, State, E, A>(
metric: Metric.Metric<Input, State>,
f: (exit: Exit.Exit<A, E>) => Input
): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>
<State, E, A>(
metric: Metric.Metric<Exit.Exit<NoInfer<A>, NoInfer<E>>, State>
): <R>(self: Effect<A, E, R>) => Effect<A, E, R>
<A, E, R, Input, State>(
self: Effect<A, E, R>,
metric: Metric.Metric<Input, State>,
f: (exit: Exit.Exit<A, E>) => Input
): Effect<A, E, R>
<A, E, R, State>(
self: Effect<A, E, R>,
metric: Metric.Metric<Exit.Exit<NoInfer<A>, NoInfer<E>>, State>
): Effect<A, E, R>Updates the Metric every time the Effect is executed.
Details
Also accepts an optional function which can be used to map the Exit value
of the Effect into a valid Input for the Metric.
Example (Incrementing a metric for each execution)
import { Effect, Metric } from "effect"
const counter = Metric.counter("effect_executions", {
description: "Counts effect executions"
}).pipe(Metric.withConstantInput(1))
const program = Effect.succeed("Hello").pipe(
Effect.track(counter)
)
// This will increment the counter by 1 when executed
Effect.runPromise(program).then(() =>
Effect.runPromise(Metric.value(counter)).then(console.log)
// Output: { count: 1, incremental: false }
)Example (Mapping exits before updating a metric)
import { Effect, Exit, Metric } from "effect"
// Track different exit types with custom mapping
const exitTracker = Metric.frequency("exit_types", {
description: "Tracks success/failure/defect counts"
})
const mapExitToString = (exit: Exit.Exit<string, Error>) => {
if (Exit.isSuccess(exit)) return "success"
if (Exit.isFailure(exit)) return "failure"
return "defect"
}
const effect = Effect.succeed("result").pipe(
Effect.track(exitTracker, mapExitToString)
)export const const track: {
<Input, State, E, A>(
metric: Metric.Metric<Input, State>,
f: (exit: Exit.Exit<A, E>) => Input
): <E, R>(
self: Effect<A, E, R>
) => Effect<A, E, R>
<State, E, A>(
metric: Metric.Metric<
Exit.Exit<NoInfer<A>, NoInfer<E>>,
State
>
): <R>(self: Effect<A, E, R>) => Effect<A, E, R>
<A, E, R, Input, State>(
self: Effect<A, E, R>,
metric: Metric.Metric<Input, State>,
f: (exit: Exit.Exit<A, E>) => Input
): Effect<A, E, R>
<A, E, R, State>(
self: Effect<A, E, R>,
metric: Metric.Metric<
Exit.Exit<NoInfer<A>, NoInfer<E>>,
State
>
): Effect<A, E, R>
}
Updates the Metric every time the Effect is executed.
Details
Also accepts an optional function which can be used to map the Exit value
of the Effect into a valid Input for the Metric.
Example (Incrementing a metric for each execution)
import { Effect, Metric } from "effect"
const counter = Metric.counter("effect_executions", {
description: "Counts effect executions"
}).pipe(Metric.withConstantInput(1))
const program = Effect.succeed("Hello").pipe(
Effect.track(counter)
)
// This will increment the counter by 1 when executed
Effect.runPromise(program).then(() =>
Effect.runPromise(Metric.value(counter)).then(console.log)
// Output: { count: 1, incremental: false }
)
Example (Mapping exits before updating a metric)
import { Effect, Exit, Metric } from "effect"
// Track different exit types with custom mapping
const exitTracker = Metric.frequency("exit_types", {
description: "Tracks success/failure/defect counts"
})
const mapExitToString = (exit: Exit.Exit<string, Error>) => {
if (Exit.isSuccess(exit)) return "success"
if (Exit.isFailure(exit)) return "failure"
return "defect"
}
const effect = Effect.succeed("result").pipe(
Effect.track(exitTracker, mapExitToString)
)
track: {
<function (type parameter) Input in <Input, State, E, A>(metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>Input, function (type parameter) State in <Input, State, E, A>(metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>State, function (type parameter) E in <Input, State, E, A>(metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>E, function (type parameter) A in <Input, State, E, A>(metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>A>(
metric: Metric.Metric<Input, State>(parameter) metric: {
Input: Contravariant<Input>;
State: Covariant<State>;
id: string;
type: Metric.Type;
description: string | undefined;
attributes: Metric.AttributeSet | undefined;
valueUnsafe: (context: Context.Context<never>) => State;
updateUnsafe: (input: Input, context: Context.Context<never>) => void;
modifyUnsafe: (input: Input, context: Context.Context<never>) => void;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
metric: import MetricMetric.interface Metric<in Input, out State>A Metric<Input, State> represents a concurrent metric which accepts update
values of type Input and are aggregated to a value of type State.
Details
For example, a counter metric would have type Metric<number, number>,
representing the fact that the metric can be updated with numbers (the amount
to increment or decrement the counter by), and the state of the counter is a
number.
There are five primitive metric types supported by Effect:
- Counters
- Frequencies
- Gauges
- Histograms
- Summaries
Example (Using multiple metric types)
import { Data, Effect, Metric } from "effect"
class MetricExample extends Data.TaggedError("MetricExample")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter: Metric.Counter<number> = Metric.counter("requests", {
description: "Total requests processed"
})
const memoryGauge: Metric.Gauge<number> = Metric.gauge("memory_usage", {
description: "Current memory usage in MB"
})
const statusFrequency: Metric.Frequency = Metric.frequency("status_codes", {
description: "HTTP status code frequency"
})
// All metrics share the same interface for updates and reads
yield* Metric.update(requestCounter, 1)
yield* Metric.update(memoryGauge, 128)
yield* Metric.update(statusFrequency, "200")
// All metrics can be read with Metric.value
const counterState = yield* Metric.value(requestCounter)
const gaugeState = yield* Metric.value(memoryGauge)
const frequencyState = yield* Metric.value(statusFrequency)
// Metrics have common properties accessible through the interface:
// - id: unique identifier
// - type: metric type ("Counter", "Gauge", "Frequency", etc.)
// - description: optional human-readable description
// - attributes: optional key-value attributes for tagging
return {
counter: {
id: requestCounter.id,
type: requestCounter.type,
state: counterState
},
gauge: { id: memoryGauge.id, type: memoryGauge.type, state: gaugeState },
frequency: {
id: statusFrequency.id,
type: statusFrequency.type,
state: frequencyState
}
}
})
The Metric namespace provides a comprehensive system for collecting, aggregating, and observing
application metrics in Effect applications.
Example (Collecting application metrics)
import { Data, Effect, Metric } from "effect"
class MetricsError extends Data.TaggedError("MetricsError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter = Metric.counter("http_requests_total")
const responseTimeHistogram = Metric.histogram("http_response_time", {
boundaries: Metric.linearBoundaries({ start: 0, width: 10, count: 10 })
})
const activeConnectionsGauge = Metric.gauge("active_connections")
const statusFrequency = Metric.frequency("http_status_codes")
// Update metrics
yield* Metric.update(requestCounter, 1)
yield* Metric.update(responseTimeHistogram, 45.2)
yield* Metric.update(activeConnectionsGauge, 12)
yield* Metric.update(statusFrequency, "200")
// Get metric values
const counterValue = yield* Metric.value(requestCounter)
const histogramValue = yield* Metric.value(responseTimeHistogram)
const gaugeValue = yield* Metric.value(activeConnectionsGauge)
const frequencyValue = yield* Metric.value(statusFrequency)
return {
counter: counterValue,
histogram: histogramValue,
gauge: gaugeValue,
frequency: frequencyValue
}
})
Metric<function (type parameter) Input in <Input, State, E, A>(metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>Input, function (type parameter) State in <Input, State, E, A>(metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>State>,
f: (exit: Exit.Exit<A, E>) => Inputf: (exit: Exit.Exit<A, E>exit: import ExitExit.type Exit<A, E = never> = Exit.Success<A, E> | Exit.Failure<A, E>Represents the result of an Effect computation.
When to use
Use when you need to synchronously inspect whether an Effect computation
succeeded or failed.
Details
An Exit<A, E> is either Success<A, E> containing a value of type A, or
Failure<A, E> containing a Cause<E> describing why the computation
failed.
Since Exit is also an Effect, you can yield it inside Effect.gen.
Example (Pattern matching on an Exit)
import { Exit } from "effect"
const success: Exit.Exit<number> = Exit.succeed(42)
const failure: Exit.Exit<number, string> = Exit.fail("error")
const result = Exit.match(success, {
onSuccess: (value) => `Got value: ${value}`,
onFailure: (cause) => `Got error: ${cause}`
})
Namespace containing helper types shared by Exit values.
When to use
Use to reference helper types that describe the shared structure of Exit
values.
Exit<function (type parameter) A in <Input, State, E, A>(metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>A, function (type parameter) E in <Input, State, E, A>(metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>E>) => function (type parameter) Input in <Input, State, E, A>(metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>Input
): <function (type parameter) E in <E, R>(self: Effect<A, E, R>): Effect<A, E, R>E, function (type parameter) R in <E, R>(self: Effect<A, E, R>): Effect<A, E, R>R>(self: Effect<A, E, R>(parameter) self: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
self: interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<function (type parameter) A in <Input, State, E, A>(metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>A, function (type parameter) E in <E, R>(self: Effect<A, E, R>): Effect<A, E, R>E, function (type parameter) R in <E, R>(self: Effect<A, E, R>): Effect<A, E, R>R>) => interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<function (type parameter) A in <Input, State, E, A>(metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): <E, R>(self: Effect<A, E, R>) => Effect<A, E, R>A, function (type parameter) E in <E, R>(self: Effect<A, E, R>): Effect<A, E, R>E, function (type parameter) R in <E, R>(self: Effect<A, E, R>): Effect<A, E, R>R>
<function (type parameter) State in <State, E, A>(metric: Metric.Metric<Exit.Exit<NoInfer<A>, NoInfer<E>>, State>): <R>(self: Effect<A, E, R>) => Effect<A, E, R>State, function (type parameter) E in <State, E, A>(metric: Metric.Metric<Exit.Exit<NoInfer<A>, NoInfer<E>>, State>): <R>(self: Effect<A, E, R>) => Effect<A, E, R>E, function (type parameter) A in <State, E, A>(metric: Metric.Metric<Exit.Exit<NoInfer<A>, NoInfer<E>>, State>): <R>(self: Effect<A, E, R>) => Effect<A, E, R>A>(
metric: Metric.Metric<
Exit.Exit<NoInfer<A>, NoInfer<E>>,
State
>
(parameter) metric: {
Input: Contravariant<Input>;
State: Covariant<State>;
id: string;
type: Metric.Type;
description: string | undefined;
attributes: Metric.AttributeSet | undefined;
valueUnsafe: (context: Context.Context<never>) => State;
updateUnsafe: (input: Input, context: Context.Context<never>) => void;
modifyUnsafe: (input: Input, context: Context.Context<never>) => void;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
metric: import MetricMetric.interface Metric<in Input, out State>A Metric<Input, State> represents a concurrent metric which accepts update
values of type Input and are aggregated to a value of type State.
Details
For example, a counter metric would have type Metric<number, number>,
representing the fact that the metric can be updated with numbers (the amount
to increment or decrement the counter by), and the state of the counter is a
number.
There are five primitive metric types supported by Effect:
- Counters
- Frequencies
- Gauges
- Histograms
- Summaries
Example (Using multiple metric types)
import { Data, Effect, Metric } from "effect"
class MetricExample extends Data.TaggedError("MetricExample")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter: Metric.Counter<number> = Metric.counter("requests", {
description: "Total requests processed"
})
const memoryGauge: Metric.Gauge<number> = Metric.gauge("memory_usage", {
description: "Current memory usage in MB"
})
const statusFrequency: Metric.Frequency = Metric.frequency("status_codes", {
description: "HTTP status code frequency"
})
// All metrics share the same interface for updates and reads
yield* Metric.update(requestCounter, 1)
yield* Metric.update(memoryGauge, 128)
yield* Metric.update(statusFrequency, "200")
// All metrics can be read with Metric.value
const counterState = yield* Metric.value(requestCounter)
const gaugeState = yield* Metric.value(memoryGauge)
const frequencyState = yield* Metric.value(statusFrequency)
// Metrics have common properties accessible through the interface:
// - id: unique identifier
// - type: metric type ("Counter", "Gauge", "Frequency", etc.)
// - description: optional human-readable description
// - attributes: optional key-value attributes for tagging
return {
counter: {
id: requestCounter.id,
type: requestCounter.type,
state: counterState
},
gauge: { id: memoryGauge.id, type: memoryGauge.type, state: gaugeState },
frequency: {
id: statusFrequency.id,
type: statusFrequency.type,
state: frequencyState
}
}
})
The Metric namespace provides a comprehensive system for collecting, aggregating, and observing
application metrics in Effect applications.
Example (Collecting application metrics)
import { Data, Effect, Metric } from "effect"
class MetricsError extends Data.TaggedError("MetricsError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter = Metric.counter("http_requests_total")
const responseTimeHistogram = Metric.histogram("http_response_time", {
boundaries: Metric.linearBoundaries({ start: 0, width: 10, count: 10 })
})
const activeConnectionsGauge = Metric.gauge("active_connections")
const statusFrequency = Metric.frequency("http_status_codes")
// Update metrics
yield* Metric.update(requestCounter, 1)
yield* Metric.update(responseTimeHistogram, 45.2)
yield* Metric.update(activeConnectionsGauge, 12)
yield* Metric.update(statusFrequency, "200")
// Get metric values
const counterValue = yield* Metric.value(requestCounter)
const histogramValue = yield* Metric.value(responseTimeHistogram)
const gaugeValue = yield* Metric.value(activeConnectionsGauge)
const frequencyValue = yield* Metric.value(statusFrequency)
return {
counter: counterValue,
histogram: histogramValue,
gauge: gaugeValue,
frequency: frequencyValue
}
})
Metric<import ExitExit.type Exit<A, E = never> = Exit.Success<A, E> | Exit.Failure<A, E>Represents the result of an Effect computation.
When to use
Use when you need to synchronously inspect whether an Effect computation
succeeded or failed.
Details
An Exit<A, E> is either Success<A, E> containing a value of type A, or
Failure<A, E> containing a Cause<E> describing why the computation
failed.
Since Exit is also an Effect, you can yield it inside Effect.gen.
Example (Pattern matching on an Exit)
import { Exit } from "effect"
const success: Exit.Exit<number> = Exit.succeed(42)
const failure: Exit.Exit<number, string> = Exit.fail("error")
const result = Exit.match(success, {
onSuccess: (value) => `Got value: ${value}`,
onFailure: (cause) => `Got error: ${cause}`
})
Namespace containing helper types shared by Exit values.
When to use
Use to reference helper types that describe the shared structure of Exit
values.
Exit<type NoInfer<A> = [A][A extends any ? 0 : never]Prevents TypeScript from inferring a type parameter from a specific
position.
When to use
Use when a function parameter must match an inferred type without becoming
an inference source.
Details
The parameter using NoInfer must still match the inferred type.
Example (Controlling inference)
import type { Types } from "effect"
declare function withDefault<T>(value: T, fallback: Types.NoInfer<T>): T
// T is inferred as "a" | "b" from the first argument only
const result = withDefault<"a" | "b">("a", "b")
NoInfer<function (type parameter) A in <State, E, A>(metric: Metric.Metric<Exit.Exit<NoInfer<A>, NoInfer<E>>, State>): <R>(self: Effect<A, E, R>) => Effect<A, E, R>A>, type NoInfer<A> = [A][A extends any ? 0 : never]Prevents TypeScript from inferring a type parameter from a specific
position.
When to use
Use when a function parameter must match an inferred type without becoming
an inference source.
Details
The parameter using NoInfer must still match the inferred type.
Example (Controlling inference)
import type { Types } from "effect"
declare function withDefault<T>(value: T, fallback: Types.NoInfer<T>): T
// T is inferred as "a" | "b" from the first argument only
const result = withDefault<"a" | "b">("a", "b")
NoInfer<function (type parameter) E in <State, E, A>(metric: Metric.Metric<Exit.Exit<NoInfer<A>, NoInfer<E>>, State>): <R>(self: Effect<A, E, R>) => Effect<A, E, R>E>>, function (type parameter) State in <State, E, A>(metric: Metric.Metric<Exit.Exit<NoInfer<A>, NoInfer<E>>, State>): <R>(self: Effect<A, E, R>) => Effect<A, E, R>State>
): <function (type parameter) R in <R>(self: Effect<A, E, R>): Effect<A, E, R>R>(self: Effect<A, E, R>(parameter) self: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
self: interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<function (type parameter) A in <State, E, A>(metric: Metric.Metric<Exit.Exit<NoInfer<A>, NoInfer<E>>, State>): <R>(self: Effect<A, E, R>) => Effect<A, E, R>A, function (type parameter) E in <State, E, A>(metric: Metric.Metric<Exit.Exit<NoInfer<A>, NoInfer<E>>, State>): <R>(self: Effect<A, E, R>) => Effect<A, E, R>E, function (type parameter) R in <R>(self: Effect<A, E, R>): Effect<A, E, R>R>) => interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<function (type parameter) A in <State, E, A>(metric: Metric.Metric<Exit.Exit<NoInfer<A>, NoInfer<E>>, State>): <R>(self: Effect<A, E, R>) => Effect<A, E, R>A, function (type parameter) E in <State, E, A>(metric: Metric.Metric<Exit.Exit<NoInfer<A>, NoInfer<E>>, State>): <R>(self: Effect<A, E, R>) => Effect<A, E, R>E, function (type parameter) R in <R>(self: Effect<A, E, R>): Effect<A, E, R>R>
<function (type parameter) A in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>A, function (type parameter) E in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>E, function (type parameter) R in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>R, function (type parameter) Input in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>Input, function (type parameter) State in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>State>(
self: Effect<A, E, R>(parameter) self: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
self: interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<function (type parameter) A in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>A, function (type parameter) E in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>E, function (type parameter) R in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>R>,
metric: Metric.Metric<Input, State>(parameter) metric: {
Input: Contravariant<Input>;
State: Covariant<State>;
id: string;
type: Metric.Type;
description: string | undefined;
attributes: Metric.AttributeSet | undefined;
valueUnsafe: (context: Context.Context<never>) => State;
updateUnsafe: (input: Input, context: Context.Context<never>) => void;
modifyUnsafe: (input: Input, context: Context.Context<never>) => void;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
metric: import MetricMetric.interface Metric<in Input, out State>A Metric<Input, State> represents a concurrent metric which accepts update
values of type Input and are aggregated to a value of type State.
Details
For example, a counter metric would have type Metric<number, number>,
representing the fact that the metric can be updated with numbers (the amount
to increment or decrement the counter by), and the state of the counter is a
number.
There are five primitive metric types supported by Effect:
- Counters
- Frequencies
- Gauges
- Histograms
- Summaries
Example (Using multiple metric types)
import { Data, Effect, Metric } from "effect"
class MetricExample extends Data.TaggedError("MetricExample")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter: Metric.Counter<number> = Metric.counter("requests", {
description: "Total requests processed"
})
const memoryGauge: Metric.Gauge<number> = Metric.gauge("memory_usage", {
description: "Current memory usage in MB"
})
const statusFrequency: Metric.Frequency = Metric.frequency("status_codes", {
description: "HTTP status code frequency"
})
// All metrics share the same interface for updates and reads
yield* Metric.update(requestCounter, 1)
yield* Metric.update(memoryGauge, 128)
yield* Metric.update(statusFrequency, "200")
// All metrics can be read with Metric.value
const counterState = yield* Metric.value(requestCounter)
const gaugeState = yield* Metric.value(memoryGauge)
const frequencyState = yield* Metric.value(statusFrequency)
// Metrics have common properties accessible through the interface:
// - id: unique identifier
// - type: metric type ("Counter", "Gauge", "Frequency", etc.)
// - description: optional human-readable description
// - attributes: optional key-value attributes for tagging
return {
counter: {
id: requestCounter.id,
type: requestCounter.type,
state: counterState
},
gauge: { id: memoryGauge.id, type: memoryGauge.type, state: gaugeState },
frequency: {
id: statusFrequency.id,
type: statusFrequency.type,
state: frequencyState
}
}
})
The Metric namespace provides a comprehensive system for collecting, aggregating, and observing
application metrics in Effect applications.
Example (Collecting application metrics)
import { Data, Effect, Metric } from "effect"
class MetricsError extends Data.TaggedError("MetricsError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter = Metric.counter("http_requests_total")
const responseTimeHistogram = Metric.histogram("http_response_time", {
boundaries: Metric.linearBoundaries({ start: 0, width: 10, count: 10 })
})
const activeConnectionsGauge = Metric.gauge("active_connections")
const statusFrequency = Metric.frequency("http_status_codes")
// Update metrics
yield* Metric.update(requestCounter, 1)
yield* Metric.update(responseTimeHistogram, 45.2)
yield* Metric.update(activeConnectionsGauge, 12)
yield* Metric.update(statusFrequency, "200")
// Get metric values
const counterValue = yield* Metric.value(requestCounter)
const histogramValue = yield* Metric.value(responseTimeHistogram)
const gaugeValue = yield* Metric.value(activeConnectionsGauge)
const frequencyValue = yield* Metric.value(statusFrequency)
return {
counter: counterValue,
histogram: histogramValue,
gauge: gaugeValue,
frequency: frequencyValue
}
})
Metric<function (type parameter) Input in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>Input, function (type parameter) State in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>State>,
f: (exit: Exit.Exit<A, E>) => Inputf: (exit: Exit.Exit<A, E>exit: import ExitExit.type Exit<A, E = never> = Exit.Success<A, E> | Exit.Failure<A, E>Represents the result of an Effect computation.
When to use
Use when you need to synchronously inspect whether an Effect computation
succeeded or failed.
Details
An Exit<A, E> is either Success<A, E> containing a value of type A, or
Failure<A, E> containing a Cause<E> describing why the computation
failed.
Since Exit is also an Effect, you can yield it inside Effect.gen.
Example (Pattern matching on an Exit)
import { Exit } from "effect"
const success: Exit.Exit<number> = Exit.succeed(42)
const failure: Exit.Exit<number, string> = Exit.fail("error")
const result = Exit.match(success, {
onSuccess: (value) => `Got value: ${value}`,
onFailure: (cause) => `Got error: ${cause}`
})
Namespace containing helper types shared by Exit values.
When to use
Use to reference helper types that describe the shared structure of Exit
values.
Exit<function (type parameter) A in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>A, function (type parameter) E in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>E>) => function (type parameter) Input in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>Input
): interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<function (type parameter) A in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>A, function (type parameter) E in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>E, function (type parameter) R in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>R>
<function (type parameter) A in <A, E, R, State>(self: Effect<A, E, R>, metric: Metric.Metric<Exit.Exit<NoInfer<A>, NoInfer<E>>, State>): Effect<A, E, R>A, function (type parameter) E in <A, E, R, State>(self: Effect<A, E, R>, metric: Metric.Metric<Exit.Exit<NoInfer<A>, NoInfer<E>>, State>): Effect<A, E, R>E, function (type parameter) R in <A, E, R, State>(self: Effect<A, E, R>, metric: Metric.Metric<Exit.Exit<NoInfer<A>, NoInfer<E>>, State>): Effect<A, E, R>R, function (type parameter) State in <A, E, R, State>(self: Effect<A, E, R>, metric: Metric.Metric<Exit.Exit<NoInfer<A>, NoInfer<E>>, State>): Effect<A, E, R>State>(
self: Effect<A, E, R>(parameter) self: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
self: interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<function (type parameter) A in <A, E, R, State>(self: Effect<A, E, R>, metric: Metric.Metric<Exit.Exit<NoInfer<A>, NoInfer<E>>, State>): Effect<A, E, R>A, function (type parameter) E in <A, E, R, State>(self: Effect<A, E, R>, metric: Metric.Metric<Exit.Exit<NoInfer<A>, NoInfer<E>>, State>): Effect<A, E, R>E, function (type parameter) R in <A, E, R, State>(self: Effect<A, E, R>, metric: Metric.Metric<Exit.Exit<NoInfer<A>, NoInfer<E>>, State>): Effect<A, E, R>R>,
metric: Metric.Metric<
Exit.Exit<NoInfer<A>, NoInfer<E>>,
State
>
(parameter) metric: {
Input: Contravariant<Input>;
State: Covariant<State>;
id: string;
type: Metric.Type;
description: string | undefined;
attributes: Metric.AttributeSet | undefined;
valueUnsafe: (context: Context.Context<never>) => State;
updateUnsafe: (input: Input, context: Context.Context<never>) => void;
modifyUnsafe: (input: Input, context: Context.Context<never>) => void;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
metric: import MetricMetric.interface Metric<in Input, out State>A Metric<Input, State> represents a concurrent metric which accepts update
values of type Input and are aggregated to a value of type State.
Details
For example, a counter metric would have type Metric<number, number>,
representing the fact that the metric can be updated with numbers (the amount
to increment or decrement the counter by), and the state of the counter is a
number.
There are five primitive metric types supported by Effect:
- Counters
- Frequencies
- Gauges
- Histograms
- Summaries
Example (Using multiple metric types)
import { Data, Effect, Metric } from "effect"
class MetricExample extends Data.TaggedError("MetricExample")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter: Metric.Counter<number> = Metric.counter("requests", {
description: "Total requests processed"
})
const memoryGauge: Metric.Gauge<number> = Metric.gauge("memory_usage", {
description: "Current memory usage in MB"
})
const statusFrequency: Metric.Frequency = Metric.frequency("status_codes", {
description: "HTTP status code frequency"
})
// All metrics share the same interface for updates and reads
yield* Metric.update(requestCounter, 1)
yield* Metric.update(memoryGauge, 128)
yield* Metric.update(statusFrequency, "200")
// All metrics can be read with Metric.value
const counterState = yield* Metric.value(requestCounter)
const gaugeState = yield* Metric.value(memoryGauge)
const frequencyState = yield* Metric.value(statusFrequency)
// Metrics have common properties accessible through the interface:
// - id: unique identifier
// - type: metric type ("Counter", "Gauge", "Frequency", etc.)
// - description: optional human-readable description
// - attributes: optional key-value attributes for tagging
return {
counter: {
id: requestCounter.id,
type: requestCounter.type,
state: counterState
},
gauge: { id: memoryGauge.id, type: memoryGauge.type, state: gaugeState },
frequency: {
id: statusFrequency.id,
type: statusFrequency.type,
state: frequencyState
}
}
})
The Metric namespace provides a comprehensive system for collecting, aggregating, and observing
application metrics in Effect applications.
Example (Collecting application metrics)
import { Data, Effect, Metric } from "effect"
class MetricsError extends Data.TaggedError("MetricsError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter = Metric.counter("http_requests_total")
const responseTimeHistogram = Metric.histogram("http_response_time", {
boundaries: Metric.linearBoundaries({ start: 0, width: 10, count: 10 })
})
const activeConnectionsGauge = Metric.gauge("active_connections")
const statusFrequency = Metric.frequency("http_status_codes")
// Update metrics
yield* Metric.update(requestCounter, 1)
yield* Metric.update(responseTimeHistogram, 45.2)
yield* Metric.update(activeConnectionsGauge, 12)
yield* Metric.update(statusFrequency, "200")
// Get metric values
const counterValue = yield* Metric.value(requestCounter)
const histogramValue = yield* Metric.value(responseTimeHistogram)
const gaugeValue = yield* Metric.value(activeConnectionsGauge)
const frequencyValue = yield* Metric.value(statusFrequency)
return {
counter: counterValue,
histogram: histogramValue,
gauge: gaugeValue,
frequency: frequencyValue
}
})
Metric<import ExitExit.type Exit<A, E = never> = Exit.Success<A, E> | Exit.Failure<A, E>Represents the result of an Effect computation.
When to use
Use when you need to synchronously inspect whether an Effect computation
succeeded or failed.
Details
An Exit<A, E> is either Success<A, E> containing a value of type A, or
Failure<A, E> containing a Cause<E> describing why the computation
failed.
Since Exit is also an Effect, you can yield it inside Effect.gen.
Example (Pattern matching on an Exit)
import { Exit } from "effect"
const success: Exit.Exit<number> = Exit.succeed(42)
const failure: Exit.Exit<number, string> = Exit.fail("error")
const result = Exit.match(success, {
onSuccess: (value) => `Got value: ${value}`,
onFailure: (cause) => `Got error: ${cause}`
})
Namespace containing helper types shared by Exit values.
When to use
Use to reference helper types that describe the shared structure of Exit
values.
Exit<type NoInfer<A> = [A][A extends any ? 0 : never]Prevents TypeScript from inferring a type parameter from a specific
position.
When to use
Use when a function parameter must match an inferred type without becoming
an inference source.
Details
The parameter using NoInfer must still match the inferred type.
Example (Controlling inference)
import type { Types } from "effect"
declare function withDefault<T>(value: T, fallback: Types.NoInfer<T>): T
// T is inferred as "a" | "b" from the first argument only
const result = withDefault<"a" | "b">("a", "b")
NoInfer<function (type parameter) A in <A, E, R, State>(self: Effect<A, E, R>, metric: Metric.Metric<Exit.Exit<NoInfer<A>, NoInfer<E>>, State>): Effect<A, E, R>A>, type NoInfer<A> = [A][A extends any ? 0 : never]Prevents TypeScript from inferring a type parameter from a specific
position.
When to use
Use when a function parameter must match an inferred type without becoming
an inference source.
Details
The parameter using NoInfer must still match the inferred type.
Example (Controlling inference)
import type { Types } from "effect"
declare function withDefault<T>(value: T, fallback: Types.NoInfer<T>): T
// T is inferred as "a" | "b" from the first argument only
const result = withDefault<"a" | "b">("a", "b")
NoInfer<function (type parameter) E in <A, E, R, State>(self: Effect<A, E, R>, metric: Metric.Metric<Exit.Exit<NoInfer<A>, NoInfer<E>>, State>): Effect<A, E, R>E>>, function (type parameter) State in <A, E, R, State>(self: Effect<A, E, R>, metric: Metric.Metric<Exit.Exit<NoInfer<A>, NoInfer<E>>, State>): Effect<A, E, R>State>
): interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<function (type parameter) A in <A, E, R, State>(self: Effect<A, E, R>, metric: Metric.Metric<Exit.Exit<NoInfer<A>, NoInfer<E>>, State>): Effect<A, E, R>A, function (type parameter) E in <A, E, R, State>(self: Effect<A, E, R>, metric: Metric.Metric<Exit.Exit<NoInfer<A>, NoInfer<E>>, State>): Effect<A, E, R>E, function (type parameter) R in <A, E, R, State>(self: Effect<A, E, R>, metric: Metric.Metric<Exit.Exit<NoInfer<A>, NoInfer<E>>, State>): Effect<A, E, R>R>
} = dual<(...args: Array<any>) => any, <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input) => Effect<A, E, R>>(isDataFirst: (args: IArguments) => boolean, body: <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input) => Effect<A, E, R>): ((...args: Array<any>) => any) & (<A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input) => Effect<A, E, R>) (+1 overload)Creates a function that can be called in data-first style or data-last
(pipe-friendly) style.
When to use
Use to expose one implementation through both direct and pipe-friendly
call styles.
Details
Pass either the arity of the uncurried function or a predicate that decides
whether the current call is data-first. Arity is the common case. Use a
predicate when optional arguments make arity ambiguous.
Example (Selecting data-first or data-last style by arity)
import { Function, pipe } from "effect"
const sum = Function.dual<
(that: number) => (self: number) => number,
(self: number, that: number) => number
>(2, (self, that) => self + that)
console.log(sum(2, 3)) // 5
console.log(pipe(2, sum(3))) // 5
Example (Defining overloads with call signatures)
import { Function, pipe } from "effect"
const sum: {
(that: number): (self: number) => number
(self: number, that: number): number
} = Function.dual(2, (self: number, that: number): number => self + that)
console.log(sum(2, 3)) // 5
console.log(pipe(2, sum(3))) // 5
Example (Selecting data-first or data-last style with a predicate)
import { Function, pipe } from "effect"
const sum = Function.dual<
(that: number) => (self: number) => number,
(self: number, that: number) => number
>(
(args) => args.length === 2,
(self, that) => self + that
)
console.log(sum(2, 3)) // 5
console.log(pipe(2, sum(3))) // 5
dual(
(args: IArgumentsargs) => const isEffect: (
u: unknown
) => u is Effect<any, any, any>
Checks whether a value is an Effect.
Example (Checking whether a value is an Effect)
import { Effect } from "effect"
console.log(Effect.isEffect(Effect.succeed(1))) // true
console.log(Effect.isEffect("hello")) // false
isEffect(args: IArgumentsargs[0]),
<function (type parameter) A in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>A, function (type parameter) E in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>E, function (type parameter) R in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>R, function (type parameter) Input in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>Input, function (type parameter) State in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>State>(
self: Effect<A, E, R>(parameter) self: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
self: interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<function (type parameter) A in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>A, function (type parameter) E in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>E, function (type parameter) R in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>R>,
metric: Metric.Metric<Input, State>(parameter) metric: {
Input: Contravariant<Input>;
State: Covariant<State>;
id: string;
type: Metric.Type;
description: string | undefined;
attributes: Metric.AttributeSet | undefined;
valueUnsafe: (context: Context.Context<never>) => State;
updateUnsafe: (input: Input, context: Context.Context<never>) => void;
modifyUnsafe: (input: Input, context: Context.Context<never>) => void;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
metric: import MetricMetric.interface Metric<in Input, out State>A Metric<Input, State> represents a concurrent metric which accepts update
values of type Input and are aggregated to a value of type State.
Details
For example, a counter metric would have type Metric<number, number>,
representing the fact that the metric can be updated with numbers (the amount
to increment or decrement the counter by), and the state of the counter is a
number.
There are five primitive metric types supported by Effect:
- Counters
- Frequencies
- Gauges
- Histograms
- Summaries
Example (Using multiple metric types)
import { Data, Effect, Metric } from "effect"
class MetricExample extends Data.TaggedError("MetricExample")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter: Metric.Counter<number> = Metric.counter("requests", {
description: "Total requests processed"
})
const memoryGauge: Metric.Gauge<number> = Metric.gauge("memory_usage", {
description: "Current memory usage in MB"
})
const statusFrequency: Metric.Frequency = Metric.frequency("status_codes", {
description: "HTTP status code frequency"
})
// All metrics share the same interface for updates and reads
yield* Metric.update(requestCounter, 1)
yield* Metric.update(memoryGauge, 128)
yield* Metric.update(statusFrequency, "200")
// All metrics can be read with Metric.value
const counterState = yield* Metric.value(requestCounter)
const gaugeState = yield* Metric.value(memoryGauge)
const frequencyState = yield* Metric.value(statusFrequency)
// Metrics have common properties accessible through the interface:
// - id: unique identifier
// - type: metric type ("Counter", "Gauge", "Frequency", etc.)
// - description: optional human-readable description
// - attributes: optional key-value attributes for tagging
return {
counter: {
id: requestCounter.id,
type: requestCounter.type,
state: counterState
},
gauge: { id: memoryGauge.id, type: memoryGauge.type, state: gaugeState },
frequency: {
id: statusFrequency.id,
type: statusFrequency.type,
state: frequencyState
}
}
})
The Metric namespace provides a comprehensive system for collecting, aggregating, and observing
application metrics in Effect applications.
Example (Collecting application metrics)
import { Data, Effect, Metric } from "effect"
class MetricsError extends Data.TaggedError("MetricsError")<{
readonly operation: string
}> {}
const program = Effect.gen(function*() {
// Create different types of metrics
const requestCounter = Metric.counter("http_requests_total")
const responseTimeHistogram = Metric.histogram("http_response_time", {
boundaries: Metric.linearBoundaries({ start: 0, width: 10, count: 10 })
})
const activeConnectionsGauge = Metric.gauge("active_connections")
const statusFrequency = Metric.frequency("http_status_codes")
// Update metrics
yield* Metric.update(requestCounter, 1)
yield* Metric.update(responseTimeHistogram, 45.2)
yield* Metric.update(activeConnectionsGauge, 12)
yield* Metric.update(statusFrequency, "200")
// Get metric values
const counterValue = yield* Metric.value(requestCounter)
const histogramValue = yield* Metric.value(responseTimeHistogram)
const gaugeValue = yield* Metric.value(activeConnectionsGauge)
const frequencyValue = yield* Metric.value(statusFrequency)
return {
counter: counterValue,
histogram: histogramValue,
gauge: gaugeValue,
frequency: frequencyValue
}
})
Metric<function (type parameter) Input in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>Input, function (type parameter) State in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>State>,
f: (exit: Exit.Exit<A, E>) => Inputf: (exit: Exit.Exit<A, E>exit: import ExitExit.type Exit<A, E = never> = Exit.Success<A, E> | Exit.Failure<A, E>Represents the result of an Effect computation.
When to use
Use when you need to synchronously inspect whether an Effect computation
succeeded or failed.
Details
An Exit<A, E> is either Success<A, E> containing a value of type A, or
Failure<A, E> containing a Cause<E> describing why the computation
failed.
Since Exit is also an Effect, you can yield it inside Effect.gen.
Example (Pattern matching on an Exit)
import { Exit } from "effect"
const success: Exit.Exit<number> = Exit.succeed(42)
const failure: Exit.Exit<number, string> = Exit.fail("error")
const result = Exit.match(success, {
onSuccess: (value) => `Got value: ${value}`,
onFailure: (cause) => `Got error: ${cause}`
})
Namespace containing helper types shared by Exit values.
When to use
Use to reference helper types that describe the shared structure of Exit
values.
Exit<function (type parameter) A in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>A, function (type parameter) E in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>E>) => function (type parameter) Input in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>Input
): interface Effect<out A, out E = never, out R = never>The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
When to use
Use when you need to represent a lazy, composable workflow that can require
services, fail with a typed error, or succeed with a typed value.
Details
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
Effect<function (type parameter) A in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>A, function (type parameter) E in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>E, function (type parameter) R in <A, E, R, Input, State>(self: Effect<A, E, R>, metric: Metric.Metric<Input, State>, f: (exit: Exit.Exit<A, E>) => Input): Effect<A, E, R>R> =>
const onExit: {
<A, E, XE = never, XR = never>(
f: (
exit: Exit.Exit<A, E>
) => Effect<void, XE, XR>
): <R>(
self: Effect<A, E, R>
) => Effect<A, E | XE, R | XR>
<A, E, R, XE = never, XR = never>(
self: Effect<A, E, R>,
f: (
exit: Exit.Exit<A, E>
) => Effect<void, XE, XR>
): Effect<A, E | XE, R | XR>
}
onExit(self: Effect<A, E, R>(parameter) self: {
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
self, (exit: Exit.Exit<A, E>exit) => {
const const input: Input | Exit.Exit<A, E>input = f: (exit: Exit.Exit<A, E>) => Inputf === var undefinedundefined ? exit: Exit.Exit<A, E>exit : internalCall<Input>(body: () => Input): InputinternalCall(() => f: (exit: Exit.Exit<A, E>) => Inputf(exit: Exit.Exit<A, E>exit))
return import MetricMetric.const update: {
<Input>(input: Input): <State>(
self: Metric<Input, State>
) => Effect<void>
<Input, State>(
self: Metric<Input, State>,
input: Input
): Effect<void>
}
update(metric: Metric.Metric<Input, State>(parameter) metric: {
Input: Contravariant<Input>;
State: Covariant<State>;
id: string;
type: Metric.Type;
description: string | undefined;
attributes: Metric.AttributeSet | undefined;
valueUnsafe: (context: Context.Context<never>) => State;
updateUnsafe: (input: Input, context: Context.Context<never>) => void;
modifyUnsafe: (input: Input, context: Context.Context<never>) => void;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
metric, const input: Input | Exit.Exit<A, E>input as any)
})
)