@rimbu/graph
Version:
Immutable Graph data structures for TypeScript
108 lines (97 loc) • 2.92 kB
text/typescript
import { OptLazy } from '@rimbu/common';
import type { Link } from './index.mjs';
/**
* A valued connection between two nodes,
* being a 3-valued tuple of which the
* first two elements are nodes and the last element a value
* @typeparam N - the node type
* @typeparam V - the value type
*/
export type ValuedLink<N, V> = [N, N, V];
export namespace ValuedLink {
export type Target<N, V> = readonly [N, V];
export function fromArgs<N, V>(
node1: N,
node2: N,
value: V
): ValuedLink<N, V> {
return [node1, node2, value];
}
}
export type ValuedGraphElement<N, V> = [N] | ValuedLink<N, V>;
export namespace ValuedGraphElement {
/**
* Returns true if the given graph element `e` is a single node.
* Instructs the compiler that the type is a 1-tuple.
* @param e - the graph element
*/
export function isSingleNode(
e: ValuedGraphElement<any, any>
): e is [unknown] {
return e.length === 1;
}
/**
* Returns true if the given graph element `e` is a 3-tuple.
* Instructs the compiler that the type is a 3-tuple.
* @param e - the graph element
*/
export function isLink(
e: ValuedGraphElement<any, any>
): e is [unknown, unknown, unknown] {
return e.length !== 1;
}
/**
* Returns the value of a single node graph element if the given element `e` is a single
* node, or the given `otherwise` fallback value otherwise.
* @param e - the graph element
* @param otherwise - (default: undefined) the fallback value to return
* if the given element is not a single node
*/
export function getSingleNode<N>(
e: ValuedGraphElement<N, any>
): N | undefined;
export function getSingleNode<N, O>(
e: ValuedGraphElement<N, any>,
otherwise?: OptLazy<O>
): N | O {
if (isSingleNode(e)) return e[0];
return OptLazy(otherwise!);
}
/**
* Returns the nodes of the link graph element if the given element `e` is
* a Link element, or undefined otherwise.
* @param e - the graph element
*/
export function getLink<N, V>(
e: ValuedGraphElement<N, V>
): Link<N> | undefined {
if (isLink(e)) return e;
return undefined;
}
/**
* Returns the element at the given `key` in the graph element `e`,
* if the element is a Link element, or returns the given `otherwise` value
* otherwise.
* @param e - the graph element
* @param key - the link key
* @param otherwise - (default: undefined) the fallback value
*/
export function getLinkElement<
N,
V,
K extends keyof ValuedGraphElement<N, V>,
>(e: ValuedGraphElement<N, V>, key: K): ValuedLink<N, V>[K] | undefined;
export function getLinkElement<
N,
V,
K extends keyof ValuedGraphElement<N, V>,
O,
>(
e: ValuedGraphElement<N, V>,
key: K,
otherwise?: OptLazy<O>
): ValuedLink<N, V>[K] | O {
if (isLink(e)) return e[key];
return OptLazy(otherwise!);
}
}