# keyed

Efficiently transforms a list of values into a list of Fx streams, using keys to track identity.

This is crucial for performance when rendering lists or managing collections of stateful entities.
When the input list changes:
- New keys cause `onValue` to be called.
- Existing keys have their `RefSubject` updated with the new value.
- Removed keys close the supplied child Scope and clean resources registered
  through it; the `onValue` run fiber remains owned by the outer parent Scope.

## Signatures

```ts
export declare const keyed: {
    <A, B extends PropertyKey, C, E2, R2>(options: KeyedOptions<A, B, C, E2, R2>): <E, R>(fx: Fx<ReadonlyArray<A>, E, R>) => Fx<ReadonlyArray<C>, E | E2 | Cause.IllegalArgumentError, R | R2 | Scope.Scope>;
    <A, E, R, B extends PropertyKey, C, E2, R2>(fx: Fx<ReadonlyArray<A>, E, R>, options: KeyedOptions<A, B, C, E2, R2>): Fx<ReadonlyArray<C>, E | E2 | Cause.IllegalArgumentError, R | R2 | Scope.Scope>;
};
```

## Why

A stable key separates identity from position. Consumers can move or update
the exact result already associated with a value instead of recreating every
result when a collection changes. This is the state-preserving substrate used
by keyed template rendering, but the combinator itself is renderer-agnostic.

## Ownership and lifetime

Each key receives its own `RefSubject` and child `Scope`. Reusing a key updates
that subject in place. Removing a key closes the child Scope and therefore the
resources registered through its supplied Scope service. The `onValue` run
fiber itself is forked in the outer parent Scope, so child-Scope closure does
not guarantee interruption of an arbitrary Fx that ignores Scope. Interrupting
the outer run closes the parent and remaining children. Source and `onValue`
failures, services, and Scope requirements remain visible in the return type.

## Ordering and failures

Each source array produces a unique-key diff. Added keys start one child Fx;
reused keys update their existing RefSubject, including moves; removed keys
have their child Scope closed. A child may emit repeatedly, replacing only
that key's latest output. Arrays follow current source order and contain the
contiguous ready prefix: a later key is withheld until every earlier key has
emitted at least once. Debounce coalesces scheduled arrays, not child Fx
values. Duplicate keys fail with `Cause.IllegalArgumentError` rather than
sharing a child lifetime.

## Examples

```ts
import { Fx } from "@typed/fx"

const rows = Fx.keyed(Fx.succeed([{ id: "a", value: 1 }]), {
  getKey: (row) => row.id,
  onValue: (row) => Fx.map(row, ({ value }) => value)
})
```
