# Fx.zipLatest

Zips two Fx streams by latest values: waits for both to emit at least once,
then emits `[left, right]` whenever **either** stream emits (using the latest
value from the other). No strict pairing; output count is the sum of
emissions from both after the first pair.

**Completion:** Completes when **both** streams have completed.
**Errors:** The first failure from either stream fails the result.

## Signatures

```ts
export declare const zipLatest: {
    <AR, ER, RR>(that: Fx<AR, ER, RR>): <AL, EL, RL>(self: Fx<AL, EL, RL>) => Fx<readonly [
        AL,
        AR
    ], EL | ER, RL | RR>;
    <AL, EL, RL, AR, ER, RR>(self: Fx<AL, EL, RL>, that: Fx<AR, ER, RR>): Fx<readonly [
        AL,
        AR
    ], EL | ER, RL | RR>;
};
```

## Why

`zipLatest` combines independent sources as state: after both initialize, either update emits one
pair containing both latest values. It does not enforce one-to-one pairing.

## Ownership and lifetime

It delegates to `tuple`: both sources run concurrently and retain one latest value each until
both complete or the consumer is interrupted.

## Examples

```ts
import { Fx } from "@typed/fx"
const latest = Fx.zipLatest(Fx.succeed(1), Fx.succeed("ready"))
```
