If you inspect the type of program
now you can notice a third type parameter inside Effect
:
Since now we ignored the third type parameter, as it was always never
(no dependencies).
As we start to compose services together this third parameter will collect a union of all the dependencies required to run the program.
The best part (again) is type-safety. All dependencies are declared on the Effect
type. This makes sure that we get a compile-time error if we forget to provide a dependency when running the final program.
We get a type error if we try to execute runPromise
on program
:
import { Effect } from "effect";
import { PokeApi } from "./PokeApi";
const program = Effect.gen(function* () {
const pokeApi = yield* PokeApi;
return yield* pokeApi.getPokemon;
});
/// 👇 Error here
Effect.runPromise(program).then(console.log);
Type 'PokeApi' is not assignable to type 'never'.
That's because every run
method in effect requires the third type parameter to be never
, meaning that all the dependencies have been provided.
export const runPromise: <A, E>(
effect: Effect<A, E, never>,
options?: { readonly signal?: AbortSignal } | undefined
) => Promise<A> = _runtime.unsafeRunPromiseEffect
How do we provide a dependency? That's the next step!