What is the problem
Effect.retry supports error type narrowing via Refinement for the until option but not for while.
With until, passing a Refinement<E, E2> narrows the output error type to E2 (the errors that stop retrying and pass through):
// Line 4260 of Effect.ts
O extends { until: Refinement<E, infer E2> } ? E2
The while option has no equivalent branch — it always preserves the full error type E, even when the predicate is a type guard.
Expected behavior
while should support Refinement<E, E2> symmetrically. When while receives a refinement that identifies the errors to keep retrying on (E2), the output error type should be narrowed to Exclude<E, E2> — the errors that cause while to return false and pass through.
Example
import { Effect, Predicate } from "effect"
declare const myEffect: Effect.Effect<void, ErrorA | ErrorB | ErrorC>
// Currently: output error is still ErrorA | ErrorB | ErrorC
const result = Effect.retry(myEffect, {
while: (e): e is ErrorA => e._tag === "ErrorA",
})
// Desired: output error narrowed to ErrorB | ErrorC
// (ErrorA is always retried, so only ErrorB | ErrorC can pass through)
Workaround
Use until with an inverted refinement:
Effect.retry(myEffect, {
until: (e): e is Exclude<typeof e, ErrorA> => e._tag !== "ErrorA",
})
This works but is less readable than the while form, especially when the intent is "retry while offline."
Suggested change
In Retry.Return, add a Refinement branch for while:
// Current (line 4259-4261):
O extends { schedule: Schedule.Schedule<infer _O, infer _I, infer _R> } ? E
: O extends { until: Refinement<E, infer E2> } ? E2
: E
// Proposed:
O extends { schedule: Schedule.Schedule<infer _O, infer _I, infer _R> } ? E
: O extends { while: Refinement<E, infer E2> } ? Exclude<E, E2>
: O extends { until: Refinement<E, infer E2> } ? E2
: E
What is the problem
Effect.retrysupports error type narrowing viaRefinementfor theuntiloption but not forwhile.With
until, passing aRefinement<E, E2>narrows the output error type toE2(the errors that stop retrying and pass through):The
whileoption has no equivalent branch — it always preserves the full error typeE, even when the predicate is a type guard.Expected behavior
whileshould supportRefinement<E, E2>symmetrically. Whenwhilereceives a refinement that identifies the errors to keep retrying on (E2), the output error type should be narrowed toExclude<E, E2>— the errors that causewhileto returnfalseand pass through.Example
Workaround
Use
untilwith an inverted refinement:This works but is less readable than the
whileform, especially when the intent is "retry while offline."Suggested change
In
Retry.Return, add aRefinementbranch forwhile: