Effect CommunityEC
Effect Community3y ago
9 replies
Erakoth

Wrapper Function with optional context

Hello everyone! I'm new to Effect so sorry if my question might be stupid.
I'm trying to create a wrapper function (foo in the example) for an existing codebase that, given a function f that returns an effect, returns a new effect that does some stuff with the f() effect.
I want to make it so that the f() effect can either require a context or not; what i am currently doing is supply the context with Effect.provideContext to f() if the context is provided to foo, otherwise not.

What i want to achieve, in the following example, is for both bar1 and bar2 to be of type Effect<never, ...>, but bar1 is currently of type Effect<TestService, ...>.

Here's the example code:

interface TestService {
    readonly instance: number;
}

const TestService = Context.Tag<TestService>();

const testServiceImpl = TestService.of({ instance: 1 });

const context = Context.make(TestService, testServiceImpl);

const testEffectWithContext = (data: number[]) =>
    TestService.pipe(
        Effect.flatMap((testService) => Effect.logInfo(data.length))
    );

const testEffectWithoutContext = (data: number[]) => Effect.succeed(data);

const foo = <TData, TRequirements, TError, TValue>(
    data: TData[],
    f: (items: TData[]) => Effect.Effect<TRequirements, TError, TValue>,
    context?: Context.Context<TRequirements>
) =>
    pipe(
        Effect.if(context !== undefined, {
            onFalse: f(data),
            onTrue: f(data).pipe(Effect.provideContext(context!)),
        }),
        Effect.flatMap((fResult) => Effect.succeed(fResult))
    );

const testData = [1, 2, 3, 4, 5, 6];
const bar1 = foo(testData, testEffectWithContext, context);
const bar2 = foo(testData, testEffectWithoutContext);


Is there a way to achieve this? Or maybe a better solution, since in this case, if i forget to pass the context and f() requires it it crashes. Thank you!
Was this page helpful?