Skip to main content
The modules in ts-chas are built to interoperate. This page shows the conversion paths you’ll use most often, why you’d reach for each one, and exactly how to write them.

Result ↔ Option

Option<T> is an alias for Result<NonNullable<T>, never>, so converting between the two is lossless in terms of your value. You’re only deciding how you want to represent the absence of data. Use result.toOption() when you’ve already handled the error in context and you want to treat an Err as simply “nothing here”. The error payload is discarded.
Use .orElse() when you’re integrating an optional value into a pipeline that requires a concrete error type. You provide the error so callers know why the value was absent.

Guard → Result

Guards are type predicates by default, but every guard chain also exposes a .parse() method that returns a Result. This is the right choice whenever you want structured validation errors that your callers can handle programmatically rather than relying on thrown exceptions. Use .parse() directly on any guard to validate a single value:
Use is.function(...).implResult() when you have a function whose inputs and outputs should be validated, and you want validation failures to surface as typed Result errors instead of unchecked exceptions:

Option → Task

Option models synchronous optional values: a cache lookup, an environment variable, a local-storage read. Task orchestrates asynchronous pipelines. Task.fromOption() bridges the two so your cache check integrates cleanly into an async flow without branching on .isSome(). Use Task.fromOption() when you want to treat a cache hit as the success path and fall through to an async fetch on a miss:
The .orElse() callback only runs when cacheTask produces an Err (i.e., when the cache was empty). A cache hit short-circuits the whole chain.

Result / ResultAsync → ResultAsync

You often work in a context where some helpers return synchronous Result and others return ResultAsync. ResultAsync.fromResult() lifts a synchronous Result into the async context so you can chain .andThen(), .map(), and other async operators uniformly.

chas.go() — mixing Result and ResultAsync

.andThen() chains are clean for two or three steps, but deeper pipelines become hard to read. chas.go() lets you write the same logic imperatively using async function* generators. Each yield* either extracts the Ok value or short-circuits by returning the Err. You can freely mix synchronous Result and ResultAsync in the same generator.
The final type collects the union of all possible error types from every yield* call, so TypeScript forces you to handle every failure mode.

Guard + Tagged Errors

When you receive an unknown value from an external boundary (a caught exception, a message bus event, an inter-frame message), you need to check whether it’s a specific tagged error before acting on it. is.tagged() from ts-chas/guard gives you a type-safe guard for exactly this. Use is.tagged() when you’re catching an unknown thrown value and need to branch on a specific error variant:
You can also pass a plain string tag when you don’t have the factory in scope: