# Chaining results

> Transform success and error payloads with map and mapErr while preserving the selected result branch.

## Useful when

- You want to prepare a value before a later caller handles the result.
- You need async transformations without losing the Result wrapper.

Use `map()` to change a successful value without touching an error. Use `mapErr()` to change the error instead. Both return a result, so the caller still decides how to handle failure.

## Transform the active payload

This function returns either a user or an error. `map()` trims a successful name, and `mapErr()` turns an error into a display message. The result type changes to `Result<string, string>` while preserving the original branch tags.

```ts
import { err, ok, type Result } from '@hulla/control'

function loadUser(): Result<{ name: string }, Error> {
  return ok({ name: ' Sam ' })
}

const displayName = loadUser()
  .map((user) => user.name.trim())
  .mapErr((error) => `Could not load user: ${error.message}`)
```

Only the callback for the active branch runs. If a mapper returns another `Result`, that value stays nested inside the outer branch.

> **Important: map changes a payload, not the branch**
>
> There is no implicit flattening or `flatMap()`. When the next operation can fail, narrow the first result and return the second, as shown in the [config checker](https://hulla.dev/guides/control/config-checker.md).

## Keep asynchronous output inside the result

Mappers may return promises. The result remains an `Ok` or `Err` containing that promise, so you can continue chaining; consume the eventual value with `await` on `pair()`, `match()`, or `unwrap()`.

```ts
const doubled = ok(Promise.resolve(20))
  .map((value) => Promise.resolve(value + 1))
  .map((value) => value * 2)

const [value] = await doubled.pair()
console.log(value) // 42
```

`await doubled` alone does not resolve the payload because the result object is not a promise. If the source promise rejects, or a mapper throws or rejects, that exception propagates; `map()` does not turn it into `Err`. Put an explicit exception boundary around work that should become a result with [`tcf()`](https://hulla.dev/docs/control/attempts.md).

Two promise shapes mean different things:

| Type                    | What to await                                                       |
| ----------------------- | ------------------------------------------------------------------- |
| `Promise<Result<T, E>>` | Await the operation, then narrow its result.                        |
| `Ok<Promise<T>>`        | Await `.unwrap()`, `.match()`, or `.pair()` to resolve the payload. |

The result wrapper isn't a promise. See [Async results](https://hulla.dev/docs/control/async.md) for both forms.
