# What Is Effect?

Effect is a TypeScript library for building robust, concurrent, and maintainable
applications. At its core is a single data type, `Effect`, that describes a
program as a **value** — a lazy blueprint of work to be done — instead of
running it immediately. Because the program is a value, Effect can give you
things that plain functions and `Promise`s cannot: errors tracked in the type
system, dependency injection that the compiler enforces, automatic resource
cleanup, structured concurrency, retries, timeouts, tracing, and more — all from
one consistent toolkit.

Here is the idea in one example. Notice that the return type tells you exactly
what this program does, including how it can fail and what it needs to run.

```ts
import { Console, Effect } from "effect"

// `Effect.gen` lets you write effectful code in a familiar imperative style.
// `yield*` runs an effect and unwraps its success value — like `await`, but for
// Effect values.
const program = Effect.gen(function* () {
  yield* Console.log("Fetching the current user...")

  // Most of your logic is just sequencing effects with `yield*`.
  const name = yield* Effect.succeed("Ada")

  yield* Console.log(`Hello, ${name}!`)

  return name
})

//      ┌─── Effect<string, never, never>
//      ▼
program
```

The type `Effect<string, never, never>` is the heart of Effect: it captures the
**success** value, the possible **errors**, and the required **dependencies** of
a computation, all at once.

## The `Effect<A, E, R>` type

Every Effect carries three type parameters:

```text
         ┌─── A: the value it produces on success
         │      ┌─── E: the way it can fail (a typed error)
         │      │      ┌─── R: the services it needs to run
         ▼      ▼      ▼
Effect<Success, Error, Requirements>
```

- **`A` (success)** — the value you get when the program completes successfully.
- **`E` (error)** — the typed, expected failures the program can produce.
  Unlike thrown exceptions, these errors are visible in the type and the
  compiler forces you to handle them. (Unexpected failures — defects — are
  tracked separately, in the `Cause`.)
- **`R` (requirements)** — the services and context the program depends on, such
  as a database, an HTTP client, or configuration. The compiler will not let you
  run an Effect until every requirement in `R` has been provided.

An `Effect` is **lazy**: building one performs no work. Nothing happens until you
hand it to a runtime via `Effect.runPromise`, `Effect.runSync`, or a platform
`runMain`. This separation between *describing* a program and *running* it is
what makes Effect composable.
**Tip:** When `E` is `never`, the program cannot fail in an expected way. When `R` is
`never`, it has no outstanding dependencies and is ready to run. You will often
write `Effect<A>` as shorthand for `Effect<A, never, never>`.

## The problems Effect solves

In ordinary TypeScript, a function's signature tells you what it returns on
success — but says nothing about how it can fail or what it secretly depends on:

```ts
// Looks total, but can throw and reads from a hidden global. The compiler
// gives you no warning about either.
const divide = (a: number, b: number): number => {
  if (b === 0) throw new Error("Cannot divide by zero")
  return a / b
}
```

Effect moves errors and dependencies into the type system, so the compiler can
help you reason about the *whole* behaviour of your program, not just the happy
path:

```ts
import { Effect } from "effect"

// The signature now documents the failure mode. Callers must handle it.
const divide = (a: number, b: number): Effect.Effect<number, Error> =>
  b === 0
    ? Effect.fail(new Error("Cannot divide by zero"))
    : Effect.succeed(a / b)
```

This single shift unlocks a whole ecosystem of capabilities that compose
cleanly, because they all speak the same `Effect` language:
**Typed errors**
Failures are values in the type system. The compiler forces you to handle
    them — no forgotten `try`/`catch`.

**Dependency injection**
Services and configuration are tracked in `R` and provided by Layers.
    Swap real implementations for mocks without touching business logic.

**Structured concurrency**
A fiber-based runtime gives you cheap concurrency, interruption, timeouts,
    and racing — with guaranteed cleanup.

**One ecosystem**
Retries, scheduling, streaming, caching, tracing, schema, HTTP, RPC and more
    — one consistent toolkit instead of a dozen dependencies.

## Where to go next

This section gets you from zero to a running Effect program:

- **[Why Effect?](https://effect.plants.sh/introduction/why-effect/)** — the motivation in more depth:
  typed errors, dependency injection, structured concurrency, and a single
  ecosystem.
- **[Installation](https://effect.plants.sh/introduction/installation/)** — set up a TypeScript project
  with Bun, npm, or pnpm.
- **[Quickstart](https://effect.plants.sh/introduction/quickstart/)** — build a small but real Effect
  program end to end.
- **[Importing Effect](https://effect.plants.sh/introduction/importing-effect/)** — how the package is
  laid out, and how to import core and unstable modules.

When you are ready to go deeper, head to [Effect Essentials](https://effect.plants.sh/essentials/) to
learn how to create, transform, and run effects, then on to
[Error Management](https://effect.plants.sh/error-management/) and [Services & Layers](https://effect.plants.sh/services-and-layers/).