From Discord: Refining Error Channels in TypeScript Effects Without Tagged Errors
Summary
Summary
The conversation revolves around refining error channels in TypeScript Effects without using tagged errors. The initial code snippet provided by the user demonstrates a custom combinator refineErrorOrDie that refines the error channel by mapping specific errors to custom tagged errors or dying otherwise. The user also mentions an alternative approach using Effect.catchAll, which requires type annotations and is not ideal.
Another participant suggests using .catch, but the user clarifies that they want to use refinements instead of discriminators. The conversation touches on the idea of using mapError, flip, filterOrDie, and flip, but this approach is deemed ugly. The user mentions that there used to be a refineOrDie function that was removed for being unsafe and misleading.
The user expresses a preference for a single combinator to handle error refinement rather than flipping between the A/E channels. The suggestion is made to create an issue requesting the return of refineErrorOrDie and refineErrorTagOrDie.
Key Takeaways
- Custom Combinator: The user has a custom combinator
refineErrorOrDiefor refining error channels. - Alternative Approach: Using
Effect.catchAllwith type annotations is an alternative but not ideal. - Refinement vs. Discriminator: The user prefers using refinements over discriminators for error handling.
- Removed Functionality: There used to be a
refineOrDiefunction that was removed for safety concerns. - Single Combinator Preference: The user prefers a single combinator for error refinement rather than multiple steps.
- Feature Request: There's a suggestion to create an issue to bring back
refineErrorOrDieandrefineErrorTagOrDie.
Action Items
- Consider creating an issue to request the return of
refineErrorOrDieandrefineErrorTagOrDiein the Effect-TS library.
Discord thread
https://discord.com/channels/795981131316985866/1252232384070422598
I would like a refineOrDie method which refines the error channel or dies based on custom logic such as refinements. This is useful for cases where I do not have a tagged error and wish to map an E to some E1 or die.
Something like so:
export const refineErrorOrDie =
<A, E, E1>(f: (e: E) => Option.Option<E1>) =>
(self: Effect.Effect<A, E>): Effect.Effect<A, E1> =>
self.pipe(
Effect.catchAll((e) =>
Option.match(f(e), {
onNone: () => Effect.die(e),
onSome: Effect.fail
})
)
)
I can accomplish the same thing with a catchAll but it requires some type annotations which isn't ideal:
Effect.catchAll((e) => {
if (isUniqueConstraintError(e)) {
return Effect.fail<Chip.AlreadyExists | Team.NotFound>(new Chip.AlreadyExists())
}
if (isForegienKeyConstraintError(e)) {
return Effect.fail<Chip.AlreadyExists | Team.NotFound>(new Team.NotFound())
}
return Effect.die(e)
})
You can use Effect.catchIf(isSomeError, Effect.die)