Matching
Matching turns an outcome into one value or selects the next computation. Use typed matching for domain failures and cause matching when a boundary needs defects and interruptions too.
Folding success and failure into values
error InvalidCount
function itemCount(raw: number) {
if (raw < 0) throw new InvalidCount()
return raw
}
function countLabel(raw: number) {
return Effect.match(itemCount(raw), {
onFailure: () => "Count unavailable",
onSuccess: (count) => `${count} items`
})
}
// string!!Effect.match applies synchronous value callbacks. Neither callback can perform an Effect operation; a callback that only formats text is eligible for plain JavaScript compilation. A cause without an expected failure propagates. If a mixed cause includes an expected failure, Effect selects that failure and can discard its other reasons; ordinary catch preserves the whole mixed cause.
Choosing effectful branches
function reportCount(raw: number) {
return Effect.matchEffect(() => itemCount(raw), {
onFailure: () => {
log("Invalid count received")
return "Count unavailable"
},
onSuccess: (count) => {
log("Count accepted")
return `${count} items`
}
})
}matchEffect accepts Effeck functions that can pause, fail, or use services. Only the selected branch runs, and its errors and requirements join the result's contract. A try/catch is also useful when the two branches are easier to read as statements.
Matching complete failure causes
function outcomeLabel() {
return Effect.matchCause(die(new Error("index invariant")), {
onFailure: (cause) => cause.hasDies() ? "Index defect" : "Index stopped",
onSuccess: () => "Index ready"
})
}
function reportOutcome() {
return Effect.matchCauseEffect(() => die(new Error("index invariant")), {
onFailure: (cause) => {
log("Index stopped", cause.reasons.map((reason) => reason._tag))
return "Unavailable"
},
onSuccess: () => "Ready"
})
}matchCause passes the full cause to a synchronous failure callback. matchCauseEffect allows Effect operations in both callbacks. These APIs can consume cancellation and mixed causes, so choose them where that handling is part of the boundary's policy.
Discarding failures or all causes
function ignoreRejectedCount() {
Effect.ignore(itemCount(-2))
}
// void!!
function discardBoundaryOutcome() {
Effect.ignoreCause(() => die(new Error("isolated task failed")))
}ignore discards the success value and typed failures. Causes without an expected failure propagate, but a mixed cause containing one can be consumed too. ignoreCause consumes the full failure cause even when it contains no expected failure. Use complete cause discarding only where losing both diagnostics and cancellation is deliberate.