<E, N>(config: AstarConfig<E, N>): <T extends Kind = "directed">(
graph: Graph<N, E, T> | MutableGraph<N, E, T>
) => Option.Option<PathResult<E>>
<N, E, T extends Kind = "directed">(
graph: Graph<N, E, T> | MutableGraph<N, E, T>,
config: AstarConfig<E, N>
): Option.Option<PathResult<E>>Finds the shortest path from the configured source node to the target node using the A* pathfinding algorithm.
Details
The edge-cost function must return non-negative weights, and the heuristic
should be consistent to preserve shortest-path guarantees. Returns
Option.none() when the target is not reachable, and throws a GraphError
when either endpoint is missing or a negative edge cost is encountered.
Example (Finding shortest paths with A-star)
import { Graph } from "effect"
const graph = Graph.directed<{ x: number; y: number }, number>((mutable) => {
const a = Graph.addNode(mutable, { x: 0, y: 0 })
const b = Graph.addNode(mutable, { x: 1, y: 0 })
const c = Graph.addNode(mutable, { x: 2, y: 0 })
Graph.addEdge(mutable, a, b, 1)
Graph.addEdge(mutable, b, c, 1)
})
// Manhattan distance heuristic
const heuristic = (
nodeData: { x: number; y: number },
targetData: { x: number; y: number }
) => Math.abs(nodeData.x - targetData.x) + Math.abs(nodeData.y - targetData.y)
const result = Graph.astar(graph, {
source: 0,
target: 2,
cost: (edgeData) => edgeData,
heuristic
})
if (result._tag === "Some") {
console.log(result.value.path) // [0, 1, 2] - shortest path
console.log(result.value.distance) // 2 - total distance
}export const const astar: {
<E, N>(config: AstarConfig<E, N>): <
T extends Kind = "directed"
>(
graph: Graph<N, E, T> | MutableGraph<N, E, T>
) => Option.Option<PathResult<E>>
<N, E, T extends Kind = "directed">(
graph: Graph<N, E, T> | MutableGraph<N, E, T>,
config: AstarConfig<E, N>
): Option.Option<PathResult<E>>
}
Finds the shortest path from the configured source node to the target node
using the A* pathfinding algorithm.
Details
The edge-cost function must return non-negative weights, and the heuristic
should be consistent to preserve shortest-path guarantees. Returns
Option.none() when the target is not reachable, and throws a GraphError
when either endpoint is missing or a negative edge cost is encountered.
Example (Finding shortest paths with A-star)
import { Graph } from "effect"
const graph = Graph.directed<{ x: number; y: number }, number>((mutable) => {
const a = Graph.addNode(mutable, { x: 0, y: 0 })
const b = Graph.addNode(mutable, { x: 1, y: 0 })
const c = Graph.addNode(mutable, { x: 2, y: 0 })
Graph.addEdge(mutable, a, b, 1)
Graph.addEdge(mutable, b, c, 1)
})
// Manhattan distance heuristic
const heuristic = (
nodeData: { x: number; y: number },
targetData: { x: number; y: number }
) => Math.abs(nodeData.x - targetData.x) + Math.abs(nodeData.y - targetData.y)
const result = Graph.astar(graph, {
source: 0,
target: 2,
cost: (edgeData) => edgeData,
heuristic
})
if (result._tag === "Some") {
console.log(result.value.path) // [0, 1, 2] - shortest path
console.log(result.value.distance) // 2 - total distance
}
astar: {
<function (type parameter) E in <E, N>(config: AstarConfig<E, N>): <T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Option.Option<PathResult<E>>E, function (type parameter) N in <E, N>(config: AstarConfig<E, N>): <T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Option.Option<PathResult<E>>N>(
config: AstarConfig<E, N>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
heuristic: (sourceNodeData: N, targetNodeData: N) => number;
}
config: interface AstarConfig<E, N>Configuration for finding a shortest path with the A* algorithm.
When to use
Use when configuring astar for point-to-point shortest-path searches where
node data can provide a heuristic estimate toward the target.
Details
Specifies the source and target node indices, an edge-cost function, and a
heuristic that estimates the remaining cost from a node to the target.
AstarConfig<function (type parameter) E in <E, N>(config: AstarConfig<E, N>): <T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Option.Option<PathResult<E>>E, function (type parameter) N in <E, N>(config: AstarConfig<E, N>): <T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Option.Option<PathResult<E>>N>
): <function (type parameter) T in <T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>): Option.Option<PathResult<E>>T extends type Kind = "directed" | "undirected"Graph type for distinguishing directed and undirected graphs.
When to use
Use when writing graph-polymorphic types or helpers that need to preserve
whether a graph is directed or undirected.
Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>graph: interface Graph<out N, out E, T extends Kind = "directed">Immutable graph interface.
When to use
Use as the immutable graph model for code that queries, traverses,
transforms, or analyzes graph structure without mutating it.
Graph<function (type parameter) N in <E, N>(config: AstarConfig<E, N>): <T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Option.Option<PathResult<E>>N, function (type parameter) E in <E, N>(config: AstarConfig<E, N>): <T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Option.Option<PathResult<E>>E, function (type parameter) T in <T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>): Option.Option<PathResult<E>>T> | interface MutableGraph<out N, out E, T extends Kind = "directed">Mutable graph interface.
When to use
Use when adding, removing, or updating nodes and edges inside a graph
mutation scope.
MutableGraph<function (type parameter) N in <E, N>(config: AstarConfig<E, N>): <T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Option.Option<PathResult<E>>N, function (type parameter) E in <E, N>(config: AstarConfig<E, N>): <T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Option.Option<PathResult<E>>E, function (type parameter) T in <T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>): Option.Option<PathResult<E>>T>) => import OptionOption.type Option<A> = Option.None<A> | Option.Some<A>The Option data type represents optional values. An Option<A> is either
Some<A>, containing a value of type A, or None, representing absence.
When to use
Use to represent initial values that may not yet exist
- Returning from partial functions (not defined for all inputs)
- Managing optional fields in data structures
Namespace containing utility types for Option.
When to use
Use to access type-level helpers associated with Option.
Option<interface PathResult<E>Result of a shortest path computation.
When to use
Use to read the successful source-to-target shortest path returned by
path-finding algorithms, including the ordered node indices, total distance,
and traversed edge data.
Details
Contains the node-index path, the total numeric distance, and the edge data
encountered along the path.
Gotchas
costs contains original edge data, not the numeric output of the cost
function unless the edge data is numeric.
PathResult<function (type parameter) E in <E, N>(config: AstarConfig<E, N>): <T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Option.Option<PathResult<E>>E>>
<function (type parameter) N in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>N, function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>E, function (type parameter) T in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>T extends type Kind = "directed" | "undirected"Graph type for distinguishing directed and undirected graphs.
When to use
Use when writing graph-polymorphic types or helpers that need to preserve
whether a graph is directed or undirected.
Kind = "directed">(
graph: Graph<N, E, T> | MutableGraph<N, E, T>graph: interface Graph<out N, out E, T extends Kind = "directed">Immutable graph interface.
When to use
Use as the immutable graph model for code that queries, traverses,
transforms, or analyzes graph structure without mutating it.
Graph<function (type parameter) N in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>N, function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>E, function (type parameter) T in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>T> | interface MutableGraph<out N, out E, T extends Kind = "directed">Mutable graph interface.
When to use
Use when adding, removing, or updating nodes and edges inside a graph
mutation scope.
MutableGraph<function (type parameter) N in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>N, function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>E, function (type parameter) T in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>T>,
config: AstarConfig<E, N>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
heuristic: (sourceNodeData: N, targetNodeData: N) => number;
}
config: interface AstarConfig<E, N>Configuration for finding a shortest path with the A* algorithm.
When to use
Use when configuring astar for point-to-point shortest-path searches where
node data can provide a heuristic estimate toward the target.
Details
Specifies the source and target node indices, an edge-cost function, and a
heuristic that estimates the remaining cost from a node to the target.
AstarConfig<function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>E, function (type parameter) N in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>N>
): import OptionOption.type Option<A> = Option.None<A> | Option.Some<A>The Option data type represents optional values. An Option<A> is either
Some<A>, containing a value of type A, or None, representing absence.
When to use
Use to represent initial values that may not yet exist
- Returning from partial functions (not defined for all inputs)
- Managing optional fields in data structures
Namespace containing utility types for Option.
When to use
Use to access type-level helpers associated with Option.
Option<interface PathResult<E>Result of a shortest path computation.
When to use
Use to read the successful source-to-target shortest path returned by
path-finding algorithms, including the ordered node indices, total distance,
and traversed edge data.
Details
Contains the node-index path, the total numeric distance, and the edge data
encountered along the path.
Gotchas
costs contains original edge data, not the numeric output of the cost
function unless the edge data is numeric.
PathResult<function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>E>>
} = import dualdual(2, <function (type parameter) N in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>N, function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>E, function (type parameter) T in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>T extends type Kind = "directed" | "undirected"Graph type for distinguishing directed and undirected graphs.
When to use
Use when writing graph-polymorphic types or helpers that need to preserve
whether a graph is directed or undirected.
Kind = "directed">(
graph: Graph<N, E, T> | MutableGraph<N, E, T>graph: interface Graph<out N, out E, T extends Kind = "directed">Immutable graph interface.
When to use
Use as the immutable graph model for code that queries, traverses,
transforms, or analyzes graph structure without mutating it.
Graph<function (type parameter) N in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>N, function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>E, function (type parameter) T in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>T> | interface MutableGraph<out N, out E, T extends Kind = "directed">Mutable graph interface.
When to use
Use when adding, removing, or updating nodes and edges inside a graph
mutation scope.
MutableGraph<function (type parameter) N in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>N, function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>E, function (type parameter) T in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>T>,
config: AstarConfig<E, N>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
heuristic: (sourceNodeData: N, targetNodeData: N) => number;
}
config: interface AstarConfig<E, N>Configuration for finding a shortest path with the A* algorithm.
When to use
Use when configuring astar for point-to-point shortest-path searches where
node data can provide a heuristic estimate toward the target.
Details
Specifies the source and target node indices, an edge-cost function, and a
heuristic that estimates the remaining cost from a node to the target.
AstarConfig<function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>E, function (type parameter) N in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>N>
): import OptionOption.type Option<A> = Option.None<A> | Option.Some<A>The Option data type represents optional values. An Option<A> is either
Some<A>, containing a value of type A, or None, representing absence.
When to use
Use to represent initial values that may not yet exist
- Returning from partial functions (not defined for all inputs)
- Managing optional fields in data structures
Namespace containing utility types for Option.
When to use
Use to access type-level helpers associated with Option.
Option<interface PathResult<E>Result of a shortest path computation.
When to use
Use to read the successful source-to-target shortest path returned by
path-finding algorithms, including the ordered node indices, total distance,
and traversed edge data.
Details
Contains the node-index path, the total numeric distance, and the edge data
encountered along the path.
Gotchas
costs contains original edge data, not the numeric output of the cost
function unless the edge data is numeric.
PathResult<function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>E>> => {
// Validate that source and target nodes exist
if (!graph: Graph<N, E, T> | MutableGraph<N, E, T>graph.Proto<out N, out E>.nodes: Map<NodeIndex, N>nodes.Map<number, N>.has(key: number): booleanhas(config: AstarConfig<E, N>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
heuristic: (sourceNodeData: N, targetNodeData: N) => number;
}
config.AstarConfig<E, N>.source: NodeIndexsource)) {
throw const missingNode: (
node: number
) => GraphError
missingNode(config: AstarConfig<E, N>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
heuristic: (sourceNodeData: N, targetNodeData: N) => number;
}
config.AstarConfig<E, N>.source: NodeIndexsource)
}
if (!graph: Graph<N, E, T> | MutableGraph<N, E, T>graph.Proto<out N, out E>.nodes: Map<NodeIndex, N>nodes.Map<number, N>.has(key: number): booleanhas(config: AstarConfig<E, N>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
heuristic: (sourceNodeData: N, targetNodeData: N) => number;
}
config.AstarConfig<E, N>.target: NodeIndextarget)) {
throw const missingNode: (
node: number
) => GraphError
missingNode(config: AstarConfig<E, N>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
heuristic: (sourceNodeData: N, targetNodeData: N) => number;
}
config.AstarConfig<E, N>.target: NodeIndextarget)
}
const const edgeWeights: Map<number, number>edgeWeights = const validateNonNegativeEdgeWeights: <
N,
E,
T extends Kind = "directed"
>(
graph: Graph<N, E, T> | MutableGraph<N, E, T>,
cost: (edgeData: E) => number,
algorithm: string
) => Map<EdgeIndex, number>
validateNonNegativeEdgeWeights(graph: Graph<N, E, T> | MutableGraph<N, E, T>graph, config: AstarConfig<E, N>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
heuristic: (sourceNodeData: N, targetNodeData: N) => number;
}
config.AstarConfig<E, N>.cost: (edgeData: E) => numbercost, "A* algorithm")
// Early return if source equals target
if (config: AstarConfig<E, N>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
heuristic: (sourceNodeData: N, targetNodeData: N) => number;
}
config.AstarConfig<E, N>.source: NodeIndexsource === config: AstarConfig<E, N>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
heuristic: (sourceNodeData: N, targetNodeData: N) => number;
}
config.AstarConfig<E, N>.target: NodeIndextarget) {
return import OptionOption.const some: <A>(value: A) => Option<A>Wraps the given value into an Option to represent its presence.
When to use
Use to wrap a known present value as Option
- Returning a successful result from a partial function
Details
- Always returns
Some<A>
- Does not filter
null or undefined; use
fromNullishOr
for that
Example (Wrapping a value)
import { Option } from "effect"
// ┌─── Option<number>
// ▼
const value = Option.some(1)
console.log(value)
// Output: { _id: 'Option', _tag: 'Some', value: 1 }
some({
path: number[]path: [config: AstarConfig<E, N>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
heuristic: (sourceNodeData: N, targetNodeData: N) => number;
}
config.AstarConfig<E, N>.source: NodeIndexsource],
distance: numberdistance: 0,
costs: never[]costs: []
})
}
// Get target node data for heuristic calculations
const const targetNodeData: Option.Option<N>targetNodeData = const getNode: {
<N, E, T extends Kind = "directed">(
nodeIndex: NodeIndex
): (
graph: Graph<N, E, T> | MutableGraph<N, E, T>
) => Option.Option<N>
<N, E, T extends Kind = "directed">(
graph: Graph<N, E, T> | MutableGraph<N, E, T>,
nodeIndex: NodeIndex
): Option.Option<N>
}
getNode(graph: Graph<N, E, T> | MutableGraph<N, E, T>graph, config: AstarConfig<E, N>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
heuristic: (sourceNodeData: N, targetNodeData: N) => number;
}
config.AstarConfig<E, N>.target: NodeIndextarget)
if (import OptionOption.const isNone: <A>(
self: Option<A>
) => self is None<A>
Checks whether an Option is None (absent).
When to use
Use when you need to branch on an absent Option before accessing .value.
Details
- Acts as a type guard, narrowing to
None<A>
Example (Checking for None)
import { Option } from "effect"
console.log(Option.isNone(Option.some(1)))
// Output: false
console.log(Option.isNone(Option.none()))
// Output: true
isNone(const targetNodeData: Option.Option<N>targetNodeData)) {
throw new constructor GraphError(): GraphErrorError thrown by graph operations when the requested graph structure is
invalid, such as referencing a missing node or using unsupported edge
weights.
When to use
Use when handling failures thrown by graph operations that reject invalid
graph structure or unsupported algorithm inputs.
GraphError({ message: stringmessage: `Missing node data for target node ${config: AstarConfig<E, N>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
heuristic: (sourceNodeData: N, targetNodeData: N) => number;
}
config.AstarConfig<E, N>.target: NodeIndextarget}` })
}
// Distance tracking (g-score) and f-score (g + h)
const const gScore: Map<number, number>gScore = new var Map: MapConstructor
new <number, number>(iterable?: Iterable<readonly [number, number]> | null | undefined) => Map<number, number> (+3 overloads)
Map<type NodeIndex = numberNode index for node identification using plain numbers.
When to use
Use when storing or passing the stable identifier of a graph node between
Graph operations.
Details
addNode allocates node identifiers from the graph's next node index.
Gotchas
A NodeIndex is an identifier, not an array offset. Removed node identifiers
are not reused.
NodeIndex, number>()
const const fScore: Map<number, number>fScore = new var Map: MapConstructor
new <number, number>(iterable?: Iterable<readonly [number, number]> | null | undefined) => Map<number, number> (+3 overloads)
Map<type NodeIndex = numberNode index for node identification using plain numbers.
When to use
Use when storing or passing the stable identifier of a graph node between
Graph operations.
Details
addNode allocates node identifiers from the graph's next node index.
Gotchas
A NodeIndex is an identifier, not an array offset. Removed node identifiers
are not reused.
NodeIndex, number>()
const const previous: Map<
number,
{ node: NodeIndex; edgeData: E } | null
>
previous = new var Map: MapConstructor
new <number, {
node: NodeIndex;
edgeData: E;
} | null>(iterable?: Iterable<readonly [number, {
node: NodeIndex;
edgeData: E;
} | null]> | null | undefined) => Map<number, {
node: NodeIndex;
edgeData: E;
} | null> (+3 overloads)
Map<type NodeIndex = numberNode index for node identification using plain numbers.
When to use
Use when storing or passing the stable identifier of a graph node between
Graph operations.
Details
addNode allocates node identifiers from the graph's next node index.
Gotchas
A NodeIndex is an identifier, not an array offset. Removed node identifiers
are not reused.
NodeIndex, { node: NodeIndexnode: type NodeIndex = numberNode index for node identification using plain numbers.
When to use
Use when storing or passing the stable identifier of a graph node between
Graph operations.
Details
addNode allocates node identifiers from the graph's next node index.
Gotchas
A NodeIndex is an identifier, not an array offset. Removed node identifiers
are not reused.
NodeIndex; edgeData: EedgeData: function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>E } | null>()
const const visited: Set<number>visited = new var Set: SetConstructor
new <number>(iterable?: Iterable<number> | null | undefined) => Set<number> (+1 overload)
Set<type NodeIndex = numberNode index for node identification using plain numbers.
When to use
Use when storing or passing the stable identifier of a graph node between
Graph operations.
Details
addNode allocates node identifiers from the graph's next node index.
Gotchas
A NodeIndex is an identifier, not an array offset. Removed node identifiers
are not reused.
NodeIndex>()
// Initialize scores
// Iterate directly over node keys
for (const const node: numbernode of graph: Graph<N, E, T> | MutableGraph<N, E, T>graph.Proto<out N, out E>.nodes: Map<NodeIndex, N>nodes.Map<number, N>.keys(): MapIterator<number>Returns an iterable of keys in the map
keys()) {
const gScore: Map<number, number>gScore.Map<number, number>.set(key: number, value: number): Map<number, number>Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated.
set(const node: numbernode, const node: numbernode === config: AstarConfig<E, N>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
heuristic: (sourceNodeData: N, targetNodeData: N) => number;
}
config.AstarConfig<E, N>.source: NodeIndexsource ? 0 : var Infinity: numberInfinity)
const fScore: Map<number, number>fScore.Map<number, number>.set(key: number, value: number): Map<number, number>Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated.
set(const node: numbernode, var Infinity: numberInfinity)
const previous: Map<
number,
{ node: NodeIndex; edgeData: E } | null
>
previous.function Map(key: number, value: { node: NodeIndex; edgeData: E } | null): Map<number, { node: NodeIndex; edgeData: E } | null>Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated.
set(const node: numbernode, null)
}
// Calculate initial f-score for source
const const sourceNodeData: Option.Option<N>sourceNodeData = const getNode: {
<N, E, T extends Kind = "directed">(
nodeIndex: NodeIndex
): (
graph: Graph<N, E, T> | MutableGraph<N, E, T>
) => Option.Option<N>
<N, E, T extends Kind = "directed">(
graph: Graph<N, E, T> | MutableGraph<N, E, T>,
nodeIndex: NodeIndex
): Option.Option<N>
}
getNode(graph: Graph<N, E, T> | MutableGraph<N, E, T>graph, config: AstarConfig<E, N>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
heuristic: (sourceNodeData: N, targetNodeData: N) => number;
}
config.AstarConfig<E, N>.source: NodeIndexsource)
if (import OptionOption.const isSome: <A>(
self: Option<A>
) => self is Some<A>
Checks whether an Option contains a value (Some).
When to use
Use when you need to branch on a present Option before accessing .value.
Details
- Acts as a type guard, narrowing to
Some<A>
Example (Checking for Some)
import { Option } from "effect"
console.log(Option.isSome(Option.some(1)))
// Output: true
console.log(Option.isSome(Option.none()))
// Output: false
isSome(const sourceNodeData: Option.Option<N>sourceNodeData)) {
const const h: numberh = config: AstarConfig<E, N>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
heuristic: (sourceNodeData: N, targetNodeData: N) => number;
}
config.AstarConfig<E, N>.heuristic: (sourceNodeData: N, targetNodeData: N) => numberheuristic(const sourceNodeData: Option.Some<N>const sourceNodeData: {
_tag: "Some";
_op: "Some";
value: A;
valueOrUndefined: A;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
sourceNodeData.Some<N>.value: Nvalue, const targetNodeData: Option.Some<N>const targetNodeData: {
_tag: "Some";
_op: "Some";
value: A;
valueOrUndefined: A;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
targetNodeData.Some<N>.value: Nvalue)
const fScore: Map<number, number>fScore.Map<number, number>.set(key: number, value: number): Map<number, number>Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated.
set(config: AstarConfig<E, N>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
heuristic: (sourceNodeData: N, targetNodeData: N) => number;
}
config.AstarConfig<E, N>.source: NodeIndexsource, const h: numberh)
}
// Priority queue using f-score (total estimated cost)
const const openSet: Array<{
node: NodeIndex
fScore: number
}>
openSet: interface Array<T>Array<{ node: NodeIndexnode: type NodeIndex = numberNode index for node identification using plain numbers.
When to use
Use when storing or passing the stable identifier of a graph node between
Graph operations.
Details
addNode allocates node identifiers from the graph's next node index.
Gotchas
A NodeIndex is an identifier, not an array offset. Removed node identifiers
are not reused.
NodeIndex; fScore: numberfScore: number }> = [
{ node: numbernode: config: AstarConfig<E, N>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
heuristic: (sourceNodeData: N, targetNodeData: N) => number;
}
config.AstarConfig<E, N>.source: NodeIndexsource, fScore: numberfScore: const fScore: Map<number, number>fScore.Map<number, number>.get(key: number): number | undefinedReturns a specified element from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map.
get(config: AstarConfig<E, N>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
heuristic: (sourceNodeData: N, targetNodeData: N) => number;
}
config.AstarConfig<E, N>.source: NodeIndexsource)! }
]
while (const openSet: Array<{
node: NodeIndex
fScore: number
}>
openSet.Array<T>.length: numberGets or sets the length of the array. This is a number one higher than the highest index in the array.
length > 0) {
// Find node with lowest f-score
let let minIndex: numberminIndex = 0
for (let let i: numberi = 1; let i: numberi < const openSet: Array<{
node: NodeIndex
fScore: number
}>
openSet.Array<T>.length: numberGets or sets the length of the array. This is a number one higher than the highest index in the array.
length; let i: numberi++) {
if (const openSet: Array<{
node: NodeIndex
fScore: number
}>
openSet[let i: numberi].fScore: numberfScore < const openSet: Array<{
node: NodeIndex
fScore: number
}>
openSet[let minIndex: numberminIndex].fScore: numberfScore) {
let minIndex: numberminIndex = let i: numberi
}
}
const const current: {
node: NodeIndex
fScore: number
}
current = const openSet: Array<{
node: NodeIndex
fScore: number
}>
openSet.Array<{ node: NodeIndex; fScore: number; }>.splice(start: number, deleteCount?: number): {
node: NodeIndex;
fScore: number;
}[] (+1 overload)
Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
splice(let minIndex: numberminIndex, 1)[0]
const const currentNode: numbercurrentNode = const current: {
node: NodeIndex
fScore: number
}
current.node: NodeIndexnode
// Skip if already visited
if (const visited: Set<number>visited.Set<number>.has(value: number): booleanhas(const currentNode: numbercurrentNode)) {
continue
}
const visited: Set<number>visited.Set<number>.add(value: number): Set<number>Appends a new element with a specified value to the end of the Set.
add(const currentNode: numbercurrentNode)
// Early termination if we reached the target
if (const currentNode: numbercurrentNode === config: AstarConfig<E, N>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
heuristic: (sourceNodeData: N, targetNodeData: N) => number;
}
config.AstarConfig<E, N>.target: NodeIndextarget) {
break
}
// Get current g-score
const const currentGScore: numbercurrentGScore = const gScore: Map<number, number>gScore.Map<number, number>.get(key: number): number | undefinedReturns a specified element from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map.
get(const currentNode: numbercurrentNode)!
// Examine all outgoing edges
const const adjacencyList: number[] | undefinedadjacencyList = graph: Graph<N, E, T> | MutableGraph<N, E, T>graph.Proto<out N, out E>.adjacency: Map<NodeIndex, Array<EdgeIndex>>adjacency.Map<number, number[]>.get(key: number): number[] | undefinedReturns a specified element from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map.
get(const currentNode: numbercurrentNode)
if (const adjacencyList: number[] | undefinedadjacencyList !== var undefinedundefined) {
for (const const edgeIndex: numberedgeIndex of const adjacencyList: number[]adjacencyList) {
const const edge: Edge<E> | undefinededge = graph: Graph<N, E, T> | MutableGraph<N, E, T>graph.Proto<out N, out E>.edges: Map<EdgeIndex, Edge<E>>edges.Map<number, Edge<E>>.get(key: number): Edge<E> | undefinedReturns a specified element from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map.
get(const edgeIndex: numberedgeIndex)
if (const edge: Edge<E> | undefinededge !== var undefinedundefined) {
const const neighbor: numberneighbor = const getTraversableNeighbor: <
E,
T extends Kind
>(
graph:
| Graph<unknown, E, T>
| MutableGraph<unknown, E, T>,
current: NodeIndex,
edge: Edge<E>
) => NodeIndex
getTraversableNeighbor(graph: Graph<N, E, T> | MutableGraph<N, E, T>graph, const currentNode: numbercurrentNode, const edge: Edge<E>const edge: {
source: number;
target: number;
data: E;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
edge)
const const weight: numberweight = const edgeWeights: Map<number, number>edgeWeights.Map<number, number>.get(key: number): number | undefinedReturns a specified element from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map.
get(const edgeIndex: numberedgeIndex)!
const const tentativeGScore: numbertentativeGScore = const currentGScore: numbercurrentGScore + const weight: numberweight
const const neighborGScore: numberneighborGScore = const gScore: Map<number, number>gScore.Map<number, number>.get(key: number): number | undefinedReturns a specified element from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map.
get(const neighbor: numberneighbor)!
// If this path to neighbor is better than any previous one
if (const tentativeGScore: numbertentativeGScore < const neighborGScore: numberneighborGScore) {
// Update g-score and previous
const gScore: Map<number, number>gScore.Map<number, number>.set(key: number, value: number): Map<number, number>Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated.
set(const neighbor: numberneighbor, const tentativeGScore: numbertentativeGScore)
const previous: Map<
number,
{ node: NodeIndex; edgeData: E } | null
>
previous.function Map(key: number, value: { node: NodeIndex; edgeData: E } | null): Map<number, { node: NodeIndex; edgeData: E } | null>Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated.
set(const neighbor: numberneighbor, { node: numbernode: const currentNode: numbercurrentNode, edgeData: EedgeData: const edge: Edge<E>const edge: {
source: number;
target: number;
data: E;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
edge.data })
// Calculate f-score using heuristic
const const neighborNodeData: Option.Option<N>neighborNodeData = const getNode: {
<N, E, T extends Kind = "directed">(
nodeIndex: NodeIndex
): (
graph: Graph<N, E, T> | MutableGraph<N, E, T>
) => Option.Option<N>
<N, E, T extends Kind = "directed">(
graph: Graph<N, E, T> | MutableGraph<N, E, T>,
nodeIndex: NodeIndex
): Option.Option<N>
}
getNode(graph: Graph<N, E, T> | MutableGraph<N, E, T>graph, const neighbor: numberneighbor)
if (import OptionOption.const isSome: <A>(
self: Option<A>
) => self is Some<A>
Checks whether an Option contains a value (Some).
When to use
Use when you need to branch on a present Option before accessing .value.
Details
- Acts as a type guard, narrowing to
Some<A>
Example (Checking for Some)
import { Option } from "effect"
console.log(Option.isSome(Option.some(1)))
// Output: true
console.log(Option.isSome(Option.none()))
// Output: false
isSome(const neighborNodeData: Option.Option<N>neighborNodeData)) {
const const h: numberh = config: AstarConfig<E, N>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
heuristic: (sourceNodeData: N, targetNodeData: N) => number;
}
config.AstarConfig<E, N>.heuristic: (sourceNodeData: N, targetNodeData: N) => numberheuristic(const neighborNodeData: Option.Some<N>const neighborNodeData: {
_tag: "Some";
_op: "Some";
value: A;
valueOrUndefined: A;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
neighborNodeData.Some<N>.value: Nvalue, const targetNodeData: Option.Some<N>const targetNodeData: {
_tag: "Some";
_op: "Some";
value: A;
valueOrUndefined: A;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
toString: () => string;
toJSON: () => unknown;
}
targetNodeData.Some<N>.value: Nvalue)
const const f: numberf = const tentativeGScore: numbertentativeGScore + const h: numberh
const fScore: Map<number, number>fScore.Map<number, number>.set(key: number, value: number): Map<number, number>Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated.
set(const neighbor: numberneighbor, const f: numberf)
// Add to open set if not visited
if (!const visited: Set<number>visited.Set<number>.has(value: number): booleanhas(const neighbor: numberneighbor)) {
const openSet: Array<{
node: NodeIndex
fScore: number
}>
openSet.function Array(...items: Array<{ node: NodeIndex; fScore: number }>): numberAppends new elements to the end of an array, and returns the new length of the array.
push({ node: numbernode: const neighbor: numberneighbor, fScore: numberfScore: const f: numberf })
}
}
}
}
}
}
}
// Check if target is reachable
const const distance: numberdistance = const gScore: Map<number, number>gScore.Map<number, number>.get(key: number): number | undefinedReturns a specified element from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map.
get(config: AstarConfig<E, N>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
heuristic: (sourceNodeData: N, targetNodeData: N) => number;
}
config.AstarConfig<E, N>.target: NodeIndextarget)!
if (const distance: numberdistance === var Infinity: numberInfinity) {
return import OptionOption.const none: <A = never>() => Option<A>Creates an Option representing the absence of a value.
When to use
Use to represent a missing or uninitialized value, such as returning "no
result" from a function.
Details
- Returns
Option<never>, which is a subtype of Option<A> for any A
- Always returns the same singleton instance
Example (Creating an empty Option)
import { Option } from "effect"
// ┌─── Option<never>
// ▼
const noValue = Option.none()
console.log(noValue)
// Output: { _id: 'Option', _tag: 'None' }
none() // No path exists
}
// Reconstruct path
const const path: Array<NodeIndex>path: interface Array<T>Array<type NodeIndex = numberNode index for node identification using plain numbers.
When to use
Use when storing or passing the stable identifier of a graph node between
Graph operations.
Details
addNode allocates node identifiers from the graph's next node index.
Gotchas
A NodeIndex is an identifier, not an array offset. Removed node identifiers
are not reused.
NodeIndex> = []
const const costs: E[]costs: interface Array<T>Array<function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>E> = []
let let currentNode: NodeIndex | nullcurrentNode: type NodeIndex = numberNode index for node identification using plain numbers.
When to use
Use when storing or passing the stable identifier of a graph node between
Graph operations.
Details
addNode allocates node identifiers from the graph's next node index.
Gotchas
A NodeIndex is an identifier, not an array offset. Removed node identifiers
are not reused.
NodeIndex | null = config: AstarConfig<E, N>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
heuristic: (sourceNodeData: N, targetNodeData: N) => number;
}
config.AstarConfig<E, N>.target: NodeIndextarget
while (let currentNode: NodeIndex | nullcurrentNode !== null) {
const path: Array<NodeIndex>path.Array<number>.unshift(...items: number[]): numberInserts new elements at the start of an array, and returns the new length of the array.
unshift(let currentNode: NodeIndex | nullcurrentNode)
const const prev: {
node: NodeIndex
edgeData: E
} | null
prev: { node: NodeIndexnode: type NodeIndex = numberNode index for node identification using plain numbers.
When to use
Use when storing or passing the stable identifier of a graph node between
Graph operations.
Details
addNode allocates node identifiers from the graph's next node index.
Gotchas
A NodeIndex is an identifier, not an array offset. Removed node identifiers
are not reused.
NodeIndex; edgeData: EedgeData: function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>E } | null = const previous: Map<
number,
{ node: NodeIndex; edgeData: E } | null
>
previous.function Map(key: number): { node: NodeIndex; edgeData: E } | null | undefinedReturns a specified element from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map.
get(let currentNode: NodeIndex | nullcurrentNode) ?? null
if (const prev: {
node: NodeIndex
edgeData: E
} | null
prev !== null) {
const costs: E[]costs.Array<E>.unshift(...items: E[]): numberInserts new elements at the start of an array, and returns the new length of the array.
unshift(const prev: {
node: NodeIndex
edgeData: E
} | null
prev.edgeData: EedgeData)
let currentNode: NodeIndex | nullcurrentNode = const prev: {
node: NodeIndex
edgeData: E
} | null
prev.node: NodeIndexnode
} else {
let currentNode: NodeIndex | nullcurrentNode = null
}
}
return import OptionOption.const some: <A>(value: A) => Option<A>Wraps the given value into an Option to represent its presence.
When to use
Use to wrap a known present value as Option
- Returning a successful result from a partial function
Details
- Always returns
Some<A>
- Does not filter
null or undefined; use
fromNullishOr
for that
Example (Wrapping a value)
import { Option } from "effect"
// ┌─── Option<number>
// ▼
const value = Option.some(1)
console.log(value)
// Output: { _id: 'Option', _tag: 'Some', value: 1 }
some({
path: number[]path,
distance: numberdistance,
costs: E[]costs
})
})