Import
import { Navigation } from "@typed/navigation";Signatures
export declare class Navigation extends Navigation_base {
static readonly origin: Effect.Effect<string, never, Navigation>;
static readonly base: Effect.Effect<string, never, Navigation>;
static readonly currentEntry: RefSubject.Computed<{
readonly id: string;
readonly key: string;
readonly url: URL;
readonly state: unknown;
readonly sameDocument: boolean;
}, never, Navigation>;
static readonly entries: RefSubject.Computed<readonly {
readonly id: string;
readonly key: string;
readonly url: URL;
readonly state: unknown;
readonly sameDocument: boolean;
}[], never, Navigation>;
static readonly transition: RefSubject.Filtered<{
readonly type: "push" | "replace" | "reload" | "traverse";
readonly from: {
readonly id: string;
readonly key: string;
readonly url: URL;
readonly state: unknown;
readonly sameDocument: boolean;
};
readonly to: {
readonly url: URL;
readonly state: unknown;
readonly sameDocument: boolean;
readonly key?: string | undefined;
};
readonly info?: unknown;
}, never, Navigation>;
static readonly canGoBack: RefSubject.Computed<boolean, never, Navigation>;
static readonly canGoForward: RefSubject.Computed<boolean, never, Navigation>;
static navigate<S>(url: string | URL, options: NavigationNavigateOptions & {
readonly state: S;
}): Effect.Effect<DestinationState<S>, NavigationError, Navigation>;
static navigate(url: string | URL, options?: NavigationNavigateOptions): Effect.Effect<Destination, NavigationError, Navigation>;
static readonly back: (options?: NavigationInfoOptions) => Effect.Effect<{
readonly id: string;
readonly key: string;
readonly url: URL;
readonly state: unknown;
readonly sameDocument: boolean;
}, NavigationError, Navigation>;
static readonly forward: (options?: NavigationInfoOptions) => Effect.Effect<{
readonly id: string;
readonly key: string;
readonly url: URL;
readonly state: unknown;
readonly sameDocument: boolean;
}, NavigationError, Navigation>;
static readonly traverseTo: (key: Destination["key"], options?: NavigationInfoOptions) => Effect.Effect<{
readonly id: string;
readonly key: string;
readonly url: URL;
readonly state: unknown;
readonly sameDocument: boolean;
}, NavigationError, Navigation>;
static updateCurrentEntry<S>(options: {
readonly state: S;
}): Effect.Effect<DestinationState<S>, NavigationError, Navigation>;
static updateCurrentEntry(options: {
readonly state: unknown;
}): Effect.Effect<Destination, NavigationError, Navigation>;
static reload<S>(options: NavigationReloadOptions & {
readonly state: S;
}): Effect.Effect<DestinationState<S>, NavigationError, Navigation>;
static reload(options?: NavigationReloadOptions): Effect.Effect<Destination, NavigationError, Navigation>;
static readonly onBeforeNavigation: <R = never, R2 = never>(handler: BeforeNavigationHandler<R, R2>) => Effect.Effect<void, never, Navigation | Scope.Scope | R | R2>;
static readonly onNavigation: <R = never, R2 = never>(handler: NavigationHandler<R, R2>) => Effect.Effect<void, never, Navigation | Scope.Scope | R | R2>;
}Why
Routers, renderers, and application code can depend on one service whether history comes from a browser, SSR memory, or a test. Current entry, entries, and transition are RefSubjects so state remains renderer-independent.
Ownership and lifetime
A provider Layer owns the service, its backend listeners, reactive state, and handler registry. Handler registration requires a Scope and unregisters through that scope’s finalizer. Each navigation Effect publishes a transition, runs before handlers sequentially, commits, clears the transition, and then runs post-commit handlers. Interruption follows Effect’s scoped cleanup.
Property: back
Traverses to the preceding retained entry when one exists.
Property: back: Why
Bounds behavior stays provider-neutral and preserves the destination’s key, id, and state.
Property: back: Ownership and lifetime
The provider computes the preceding index and owns the resulting traversal transition. At the lower bound it returns the current Destination without creating backend work.
Property: base
The structural base path exposed by the active provider.
Property: base: Why
Routers can establish a stable mount root separately from the changing current URL.
Property: base: Ownership and lifetime
Navigation.base reads the active service synchronously; the provider owns the stored string for its Layer lifetime.
Property: canGoBack
Whether the retained history contains a preceding entry.
Property: canGoBack: Why
Callers can disable back actions without duplicating provider bounds logic.
Property: canGoBack: Ownership and lifetime
Navigation.canGoBack is a provider-backed RefSubject view. The provider owns its state; each consumer Scope owns and releases its observation.
Property: canGoForward
Whether the retained history contains a following entry.
Property: canGoForward: Why
Callers can disable forward actions after pushes truncate the forward branch.
Property: canGoForward: Ownership and lifetime
Navigation.canGoForward is a provider-backed RefSubject view. The provider owns its state; each consumer Scope owns and releases its observation.
Property: currentEntry
The reactive committed destination at the active history index.
Property: currentEntry: Why
Readers observe committed history. A before-navigation decision can still cancel or redirect the separate proposed transition without changing this value. A committed destination does not imply that the selected page has finished loading data or mounting its DOM.
Property: currentEntry: Ownership and lifetime
Navigation.currentEntry is a provider-backed RefSubject view. The provider owns its state; each consumer Scope owns and releases its observation.
Property: entries
The reactive retained history entries in traversal order.
Property: entries: Why
Back, forward, and keyed traversal need an explicit bounded history model in every provider.
Property: entries: Ownership and lifetime
Navigation.entries is a provider-backed RefSubject view. The provider owns its state; each consumer Scope owns and releases its observation.
Property: forward
Traverses to the following retained entry when one exists.
Property: forward: Why
Bounds behavior stays provider-neutral and preserves forward-history identity.
Property: forward: Ownership and lifetime
The provider computes the following index and owns the resulting traversal transition. At the upper bound it returns the current Destination without creating backend work.
Method: navigate
Starts a push or replacement transition to a URL.
Method: navigate: Why
All backends use the same ordered guard, redirect, commit, and post-commit protocol.
Method: navigate: Ownership and lifetime
The provider owns the proposed transition until it commits, redirects, cancels, fails, or is interrupted. Once its backend mutation commits, later interruption cannot undo that mutation.
Property: onBeforeNavigation
Registers a scoped pre-commit navigation handler.
Property: onBeforeNavigation: Why
Handlers can allow, redirect, or cancel before the backend mutates history.
Property: onBeforeNavigation: Ownership and lifetime
Registration captures the current Effect context and requires Scope. Closing that Scope unregisters the handler and releases retained references.
Property: onNavigation
Registers a scoped post-commit navigation handler.
Property: onNavigation: Why
Follow-up synchronization runs only after history and current-entry state agree.
Property: onNavigation: Ownership and lifetime
Registration captures the current Effect context and requires Scope. Closing that Scope unregisters the handler and releases retained references.
Property: origin
The absolute origin used to resolve relative destinations.
Property: origin: Why
A single origin makes same-document classification and URL normalization consistent across providers.
Property: origin: Ownership and lifetime
Navigation.origin reads the active service synchronously; the provider owns the stored string for its Layer lifetime.
Method: reload
Reloads the current destination through the active backend.
Method: reload: Why
Reload behavior remains explicit without pretending it is a push or keyed traversal.
Method: reload: Ownership and lifetime
The active provider owns reload work and decides whether the platform can remain in-process. Browser reload may leave the current JavaScript lifetime once the History API action commits.
Property: transition
The reactive transition while navigation is pending.
Property: transition: Why
Renderers can show pending work without treating a proposal as the committed destination.
Property: transition: Ownership and lifetime
Navigation.transition is a provider-backed RefSubject view. The provider owns its state; each consumer Scope owns and releases its observation.
Use transition.asComputed() when pending UI must observe Option.none() as the transition
ends. The Filtered observation itself emits only present transitions, so it cannot signal
absence by publishing another Transition. Reading it while absent has the usual Filtered
NoSuchElementError behavior.
Property: traverseTo
Traverses to a retained entry by stable key.
Property: traverseTo: Why
A key addresses history identity even when several entries share the same URL.
Property: traverseTo: Ownership and lifetime
The provider owns keyed lookup and the resulting backend traversal. The current key is a no-op;
an unknown key fails with NavigationError before any backend commit.
Method: updateCurrentEntry
Replaces application state on the current committed entry.
Method: updateCurrentEntry: Why
State updates should not create a new navigation position or remount the selected route.
Method: updateCurrentEntry: Ownership and lifetime
The provider owns the replacement transition and retains the supplied state only if it commits. The existing Destination key and history position remain current.
Examples
import { Navigation } from "@typed/navigation/Navigation"
import * as Effect from "effect/Effect"
const goToAccount = Navigation.navigate("/account", { history: "push" })
const current = Navigation.currentEntry
Effect service and Scope concepts follow the Effect v4 model documented at https://effect.website/docs/requirements-management/services/ and https://effect.website/docs/resource-management/scope/.
Other public imports
These import paths expose the same declaration. Each page retains its own public name and signature.
Source
packages/navigation/src/Navigation.ts:188packages/navigation/src/Navigation.ts:381packages/navigation/src/Navigation.ts:253packages/navigation/src/Navigation.ts:321packages/navigation/src/Navigation.ts:337packages/navigation/src/Navigation.ts:270packages/navigation/src/Navigation.ts:286packages/navigation/src/Navigation.ts:397packages/navigation/src/Navigation.ts:355packages/navigation/src/Navigation.ts:359packages/navigation/src/Navigation.ts:477packages/navigation/src/Navigation.ts:493packages/navigation/src/Navigation.ts:239packages/navigation/src/Navigation.ts:454packages/navigation/src/Navigation.ts:457packages/navigation/src/Navigation.ts:305packages/navigation/src/Navigation.ts:413packages/navigation/src/Navigation.ts:430packages/navigation/src/Navigation.ts:433