esteban@devtrillo:~/blog/writing$
← cd -
$ cat learning-effect-2-building-tiny-effects.md

Part 2: Building Tiny Effects

Jul 11, 2026·1 min read
$ tail -f learning-effect-2-building-tiny-effects/readers
connecting…

The first Effect post gave me the shape:

Effect.Effect<Success, Error, Requirements>;

Now I want the smallest thing I can build with it.

No services. No architecture. No big theory.

Just success and failure.

A successful Effect

import { Effect } from "effect";
const answer = Effect.succeed(42);

The type is:

Effect.Effect<number, never, never>;

Read it slowly:

This Effect gives you a number. It cannot fail. It needs nothing.

What does Effect.succeed(42) put in the success slot?

A failed Effect

class MissingName {
readonly _tag = "MissingName";
}
const failed = Effect.fail(new MissingName());

The type is:

Effect.Effect<never, MissingName, never>;

That looks weird at first.

But it makes sense. This Effect does not produce a success value. It only fails.

So the success slot is never.

What does Effect.fail(new MissingName()) put in the error slot?

The pipe is just the path

Effect code often uses .pipe(...).

const program = Effect.succeed("trillo").pipe(
Effect.map((name) => name.toUpperCase()),
);

This reads as:

  1. start with "trillo"
  2. turn it into uppercase
  3. return a new Effect

The program still has not run.

It is still a description.

After mapping 'trillo' to uppercase, what is the success type?

What I am taking with me

succeed and fail are not magic.

They are just the two smallest Effect values:

Effect.succeed(value);
Effect.fail(error);

One fills the success slot.

One fills the error slot.

NOTE

If this feels too small, good. I want the boring pieces to feel boring before the bigger pieces show up