Skip to content

Commit 037182f

Browse files
committed
feat: addEdge now edge properties if their type is defined
1 parent 4b52c10 commit 037182f

4 files changed

Lines changed: 34 additions & 8 deletions

File tree

graph.spec-d.ts

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { describe, expectTypeOf, it } from 'vitest';
2-
import { Graph } from "./src/index.js";
2+
import { Graph } from './src/index.js';
33

44
/**
55
* Those tests are not run. Their sole purpose is to test the types.
@@ -16,7 +16,7 @@ describe('graph types', () => {
1616
const g = new Graph<string, { type: 'foo' | 'bar' }>();
1717
const props = g.getEdgeProperties('a', 'b');
1818

19-
expectTypeOf(props).toEqualTypeOf<{ type: 'foo' | 'bar'}>();
19+
expectTypeOf(props).toEqualTypeOf<{ type: 'foo' | 'bar' }>();
2020
});
2121

2222
it('should only accept nodes of the given type', () => {
@@ -33,5 +33,24 @@ describe('graph types', () => {
3333

3434
// @ts-expect-error Wrong properties type
3535
g.setEdgeProperties('a', 'b', { type: 'nope' });
36-
})
37-
});
36+
});
37+
38+
it('should require edge properties if LinkProps is defined', () => {
39+
const g = new Graph<string, { type: string }>();
40+
41+
g.addEdge('a', 'b', undefined, { type: 'foo' });
42+
g.addEdge('a', 'b', 1, { type: 'foo' });
43+
44+
// @ts-expect-error
45+
g.addEdge('a', 'b', 1);
46+
});
47+
48+
it('should not allow edge properties if LinkProps is never', () => {
49+
const g = new Graph<string>();
50+
g.addEdge('a', 'b');
51+
g.addEdge('a', 'b', 1);
52+
53+
// @ts-expect-error Graph<string, never> does not allow edge properties
54+
g.addEdge('a', 'b', 1, 'notAllowed');
55+
});
56+
});

src/Graph.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { invariant } from './invariant.js';
22
import { EdgeWeight, SerializedInput } from './types.js';
33
import { deserializeGraph } from './utils/deserializeGraph.js';
44

5-
export class Graph<Node = string, LinkProps = unknown> {
5+
export class Graph<Node = string, LinkProps = never> {
66
/**
77
* The adjacency list of the graph.
88
*/
@@ -135,7 +135,14 @@ export class Graph<Node = string, LinkProps = unknown> {
135135
* Adds an edge from the `source` node to `target` node.
136136
* This method will create the nodes if they were not already added.
137137
*/
138-
addEdge(source: Node, target: Node, weight?: EdgeWeight, linkProps?: LinkProps): this {
138+
addEdge(
139+
source: Node,
140+
target: Node,
141+
...opts: [LinkProps] extends [never]
142+
? [weight?: EdgeWeight]
143+
: [weight: EdgeWeight | undefined, linkProps: LinkProps]
144+
): this {
145+
const [weight, linkProps] = opts;
139146
this.addNode(source);
140147
this.addNode(target);
141148
const adjacentNodes = this.adjacent(source);

src/utils/cloneGraph.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export function cloneGraph<Node, LinkProps>(
1111

1212
for (let [source, targets] of graph.edges.entries()) {
1313
targets.forEach((target) => {
14-
clone.addEdge(source, target);
14+
clone.addEdge.apply(clone, [source, target] as never);
1515

1616
const edgeWeight = graph.edgeWeights.get(source)?.get(target);
1717

src/utils/deserializeGraph.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export function deserializeGraph<Node, LinkProps>(
1111
});
1212

1313
data.links.forEach((link) => {
14-
g.addEdge(link.source, link.target, link.weight);
14+
g.addEdge.apply(g, [link.source, link.target, link.weight, link.props] as never);
1515
});
1616

1717
return g;

0 commit comments

Comments
 (0)