Understanding Service Implementations and Effect Composition in Effect Typescript

I have a question about how service implementations are passed down to functions inside it. My expectation for how it worked is that if you have an Effect that is composed of other Effects, the requirements pile up successively until you provide an implementation, and then that applies to everything its used.

In this example, it looks like the services are not passed to doA and doB as I would have expected. I assume since doA and doB are not invoked inside of test it doesn't count or something? Thanks in advance for the help.

class A extends Effect.Service<A>()("A", {
    effect: Effect.gen(function*() {
        return Effect.succeed('')
    })
}) {}

class B extends Effect.Service<B>()("B", {
    effect: Effect.gen(function*() {
        return Effect.succeed(true)
    })
}) {}

const doA = pipe(
    A,
    Effect.flatMap((a) => a)
)

const doB = pipe(
    B, 
    Effect.flatMap((b) => b)
)

class Test extends Effect.Service<Test>()("Testy", {
    effect: Effect.gen(function*() {
        return {
            doA,
            doB
        }
    }),
}) {}

const LettersLayer = Layer.merge(A.Default, B.Default)

const test = Effect.gen(function*() { // Effect.Effect<Test, never, never>
    const derp = yield* Test
    return derp // Test
}).pipe(Effect.provide(Layer.merge(Test.Default, LettersLayer)))

const test2 = Effect.gen(function*() { //  Effect.Effect<void, never, A | B>
    const derp2 = yield* test
    const here = derp2.doA // Effect.Effect<string, never, A>
    const here2 = derp2.doB // Effect.Effect<boolean, never, B>
    const blah = yield* here
    const blah2 = yield* here2
})
Was this page helpful?