Skip to content

Commit 6f35c01

Browse files
committed
feat(json-crdt): 🎸 add inner type safety to toSchema()
1 parent 1a3ec66 commit 6f35c01

File tree

2 files changed

+21
-9
lines changed

2 files changed

+21
-9
lines changed

src/json-crdt/schema/__tests__/toSchema.spec.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,14 @@ test('can infer schema of a document nodes', () => {
7676
expect(cmp(obj, objSchema)).toBe(true);
7777
expect(cmp(con, objSchema)).toBe(false);
7878
});
79+
80+
test('can infer schema of a typed model', () => {
81+
const schema = s.obj({
82+
id: s.con('id'),
83+
val: s.val(s.str('world')),
84+
});
85+
const model = Model.withLogicalClock().setSchema(schema);
86+
const schema2 = toSchema(model.root.node());
87+
expect(schema2.obj.id).toBeInstanceOf(nodes.con);
88+
expect(schema2.obj.val).toBeInstanceOf(nodes.val);
89+
});

src/json-crdt/schema/toSchema.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {JsonNode, ConNode, ValNode, ObjNode, VecNode, StrNode, BinNode, ArrNode} from "../nodes";
22
import {NodeBuilder, s} from "../../json-crdt-patch";
3+
import type {JsonNodeToSchema} from "./types";
34

45
/**
56
* Converts any JSON CRDT node to a schema representation. The schema can be
@@ -11,27 +12,27 @@ import {NodeBuilder, s} from "../../json-crdt-patch";
1112
* @param node JSON CRDT node to recursively convert to schema.
1213
* @returns Schema representation of the JSON CRDT node.
1314
*/
14-
export const toSchema = (node: JsonNode): NodeBuilder => {
15-
if (node instanceof ConNode) return s.con(node.val);
16-
if (node instanceof ValNode) return s.val(toSchema(node.node()));
15+
export const toSchema = <N extends JsonNode<any>>(node: N): JsonNodeToSchema<N> => {
16+
if (node instanceof ConNode) return s.con(node.val) as any;
17+
if (node instanceof ValNode) return s.val(toSchema(node.node())) as any;
1718
if (node instanceof ObjNode) {
1819
const obj: Record<string, NodeBuilder> = {};
1920
node.nodes((child, key) => obj[key] = toSchema(child));
20-
return s.obj(obj);
21+
return s.obj(obj) as any;
2122
}
2223
if (node instanceof VecNode) {
2324
const arr: NodeBuilder[] = [];
2425
node.children((child) => arr.push(toSchema(child)));
25-
return s.vec(...arr);
26+
return s.vec(...arr) as any;
2627
}
27-
if (node instanceof StrNode) return s.str(node.view());
28-
if (node instanceof BinNode) return s.bin(node.view());
28+
if (node instanceof StrNode) return s.str(node.view()) as any;
29+
if (node instanceof BinNode) return s.bin(node.view()) as any;
2930
if (node instanceof ArrNode) {
3031
const arr: NodeBuilder[] = [];
3132
node.children((child) => {
3233
if (child) arr.push(toSchema(child));
3334
});
34-
return s.arr(arr);
35+
return s.arr(arr) as any;
3536
}
36-
return s.con(undefined);
37+
return s.con(undefined) as any;
3738
};

0 commit comments

Comments
 (0)