Skip to content

Array Observable

Mubarrat edited this page Aug 8, 2025 · 1 revision

Type: ArrayChange<T>

Describes the shape of mutation change events emitted by an arrayObservable.

Overview

This type models the various mutation operations possible on an observable array. It provides precise descriptions of array mutations such as insertions, removals, replacements, reversals, sorting, and index mappings.

By modeling mutations explicitly, consumers can react specifically to the kind of change that occurred.


Type Parameters

Parameter Description
T The type of elements in the array

Variants

Variant Properties Description
Insertion/Removal/Replacement index: number
newItems?: T[]
oldItems?: T[]
Describes insertions, removals, or replacements at a given index.
Reversal reversed: true Indicates the entire array was reversed.
Sorting sortFn: ((a: T, b: T) => number) | null Describes a sorting operation with an optional comparator.
Sorted Indices Mapping sortedIndices: number[] Maps new indices to old indices after sorting or reordering.

Examples

// Insert new items at index 2
const insertion: ArrayChange<string> = {
  index: 2,
  newItems: ["hello", "world"]
};

// Reverse operation
const reversal: ArrayChange<number> = {
  reversed: true
};

// Sort operation with comparator
const sort: ArrayChange<number> = {
  sortFn: (a, b) => a - b
};

// Sorted indices mapping (new index -> old index)
const sortedIndicesChange: ArrayChange<number> = {
  sortedIndices: [2, 0, 1]
};

Interface: arrayObservable<T = any>

A reactive observable array type that extends native array behavior with fine-grained mutation events, proxy-based access, and reactive bindings.


Type Parameters

Parameter Description
T The type of elements in the array

Description

The arrayObservable wraps a native array and provides:

  • Transparent proxy access via numeric indices and length property.
  • Fine-grained, structured mutation events describing insertions, removals, reorderings, and replacements.
  • Support for optimistic updates with rollback on async failure.
  • Read-only mapped projections synchronized with source changes.
  • Compatibility with baseObservable patterns.

It is designed for reactive programming scenarios where precise updates to consumers (e.g., UI) are essential.


Inherits

  • baseObservable<T[]> — inherits core observable functionality.
  • Array<T> — implements standard array behavior.

Methods

notifyBefore(change: ArrayChange<T>): boolean

  • Purpose: Notify listeners before a mutation is applied.

  • Dispatches a valuechanging event containing a structured description of the planned mutation.

  • Listeners can cancel the mutation by calling preventDefault() on the event.

  • Parameters:

    • change — The intended mutation, described by ArrayChange<T>.
  • Returns: true if mutation should proceed; false if canceled.

Example:

observableArray.addEventListener('valuechanging', (e) => {
  if (someCondition) e.preventDefault(); // cancel mutation
});

const allowed = observableArray.notifyBefore({ index: 0, newItems: [42] });
if (allowed) {
  // proceed with mutation
}

notify(change: ArrayChange<T>): void

  • Purpose: Notify listeners after a mutation has been applied.

  • Dispatches a valuechanged event describing the mutation.

  • Parameters:

    • change — The mutation that just occurred.

Example:

observableArray.addEventListener('valuechanged', (e) => {
  console.log('Array mutated:', e);
});
observableArray.notify({ index: 1, oldItems: [10], newItems: [20] });

tryChange<TResult>(fn: () => TResult, change: ArrayChange<T>): TResult | undefined

  • Purpose: Attempt an atomic mutation wrapped with notifyBefore and notify.

  • If notifyBefore returns false, the mutation is canceled, and no changes occur.

  • Parameters:

    • fn — A synchronous function performing the mutation, returns a result.
    • change — Description of the mutation for notifications.
  • Returns: The return value of fn if successful; undefined if canceled.

Example:

const result = observableArray.tryChange(() => {
  observableArray.push(5);
  return observableArray.length;
}, { index: observableArray.length, newItems: [5] });

if (result === undefined) {
  console.log('Mutation was canceled');
} else {
  console.log('New length:', result);
}

optimistic<R>(updater: (current: arrayObservable<T>) => void, promise: Promise<R>): Promise<R>

  • Purpose: Apply optimistic updates with rollback on async failure.

  • The synchronous updater function applies immediate mutations.

  • If promise resolves, changes are kept.

  • If promise rejects, all mutations applied by updater are rolled back.

  • Parameters:

    • updater — Synchronous mutation function.
    • promise — Asynchronous operation representing the update.
  • Returns: The original promise for chaining.

Notes:

  • updater must be synchronous; async mutations inside it are not tracked.
  • Useful for optimistic UI updates that revert on errors.

Example:

const updatePromise = fetch('/api/update', { method: 'POST', body: JSON.stringify(data) });

observableArray.optimistic(
  arr => arr.push(newItem),
  updatePromise
).catch(() => {
  console.error('Update failed, changes reverted.');
});

Properties

bind

  • Inherits bind from baseObservable (observable mapping and computed support).

  • Extends with:

    • __observable__: Reference to self (for internal or advanced usage).

    • map<U>(mapper: (item: T, index: number, array: arrayObservable<T>) => U): arrayObservable<U>

      • Creates a read-only mapped projection of the array.
      • The mapped observable array stays synchronized with source mutations.
      • The mapped array is immutable; mutation attempts throw errors.

Example:

const source = arrayObservable([1, 2, 3]);
const squares = source.bind.map(x => x * x);

squares.addEventListener('valuechanged', e => {
  console.log('Squares updated:', e);
});

source.push(4);
// squares is now [1, 4, 9, 16]

Interface: arrayObservableConstructor

Constructor interface for creating arrayObservable instances.


Call Signatures

<T>(initialValues: Iterable<T> | ArrayLike<T> | number): arrayObservable<T>;
  • Create an observable array from:

    • An iterable of initial values,
    • An array-like object,
    • A number specifying length (filled with undefined).

Properties

Property Type Description
prototype arrayObservable Prototype for all observable arrays

Factory: arrayObservable

  • Wraps a native array with a Proxy to provide transparent reactive behavior.
  • Intercepts mutation methods to emit detailed change events.
  • Implements all standard array methods.
  • Integrates tightly with baseObservable pattern.

Summary

The arrayObservable provides a powerful, reactive array abstraction that supports detailed mutation tracking, optimistic updates, and derived reactive arrays. Its fine-grained change events enable efficient UI updates and consistent state synchronization.