mirror of
https://github.com/loro-dev/loro.git
synced 2025-02-02 11:06:14 +00:00
fix: refine isContainer & getType
This commit is contained in:
parent
acdcb14367
commit
d9d28ada61
2 changed files with 92 additions and 10 deletions
|
@ -1,5 +1,5 @@
|
|||
export * from "loro-wasm";
|
||||
import { Container, ContainerType, Delta, OpId, Value } from "loro-wasm";
|
||||
import { Container, ContainerType, Delta, LoroText, LoroTree, OpId, Value } from "loro-wasm";
|
||||
import { PrelimText, PrelimList, PrelimMap } from "loro-wasm";
|
||||
import { ContainerID, Loro, LoroList, LoroMap, TreeID } from "loro-wasm";
|
||||
|
||||
|
@ -89,8 +89,8 @@ export type MapDiff = {
|
|||
export type TreeDiff = {
|
||||
type: "tree";
|
||||
diff:
|
||||
| { target: TreeID; action: "create" | "delete" }
|
||||
| { target: TreeID; action: "move"; parent: TreeID };
|
||||
| { target: TreeID; action: "create" | "delete" }
|
||||
| { target: TreeID; action: "move"; parent: TreeID };
|
||||
};
|
||||
|
||||
export type Diff = ListDiff | TextDiff | MapDiff | TreeDiff;
|
||||
|
@ -107,21 +107,61 @@ export function isContainerId(s: string): s is ContainerID {
|
|||
|
||||
export { Loro };
|
||||
|
||||
/** Whether the value is a container.
|
||||
*
|
||||
* # Example
|
||||
*
|
||||
* ```ts
|
||||
* const doc = new Loro();
|
||||
* const map = doc.getMap("map");
|
||||
* const list = doc.getList("list");
|
||||
* const text = doc.getText("text");
|
||||
* isContainer(map); // true
|
||||
* isContainer(list); // true
|
||||
* isContainer(text); // true
|
||||
* isContainer(123); // false
|
||||
* isContainer("123"); // false
|
||||
* isContainer({}); // false
|
||||
*/
|
||||
export function isContainer(value: any): value is Container {
|
||||
if (typeof value !== "object" || value == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const p = value.__proto__;
|
||||
return p.hasOwnProperty("kind") && CONTAINER_TYPES.includes(value.kind());
|
||||
if (p == null || typeof p !== "object" || typeof p["kind"] !== "function") {
|
||||
return false;
|
||||
}
|
||||
|
||||
return CONTAINER_TYPES.includes(value.kind());
|
||||
}
|
||||
|
||||
export function valueType(value: any): "Json" | ContainerType {
|
||||
/** Get the type of a value that may be a container.
|
||||
*
|
||||
* # Example
|
||||
*
|
||||
* ```ts
|
||||
* const doc = new Loro();
|
||||
* const map = doc.getMap("map");
|
||||
* const list = doc.getList("list");
|
||||
* const text = doc.getText("text");
|
||||
* getType(map); // "Map"
|
||||
* getType(list); // "List"
|
||||
* getType(text); // "Text"
|
||||
* getType(123); // "Json"
|
||||
* getType("123"); // "Json"
|
||||
* getType({}); // "Json"
|
||||
* ```
|
||||
*/
|
||||
export function getType<T>(value: T): T extends LoroText ? "Text" :
|
||||
T extends LoroMap ? "Map" :
|
||||
T extends LoroTree ? "Tree" :
|
||||
T extends LoroList ? "List" : "Json" {
|
||||
if (isContainer(value)) {
|
||||
return value.kind();
|
||||
}
|
||||
|
||||
return "Json";
|
||||
return "Json" as any;
|
||||
}
|
||||
|
||||
declare module "loro-wasm" {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { describe, expect, expectTypeOf, it } from "vitest";
|
||||
import {
|
||||
Loro,
|
||||
LoroList,
|
||||
|
@ -6,7 +6,7 @@ import {
|
|||
isContainer,
|
||||
setPanicHook,
|
||||
toEncodedVersion,
|
||||
valueType,
|
||||
getType,
|
||||
} from "../src";
|
||||
import { Container } from "../dist/loro";
|
||||
|
||||
|
@ -106,8 +106,8 @@ describe("list", () => {
|
|||
list.insertContainer(2, "Text");
|
||||
const t = list.toArray()[2];
|
||||
expect(isContainer(t)).toBeTruthy();
|
||||
expect(valueType(t)).toBe("Text");
|
||||
expect(valueType(123)).toBe("Json");
|
||||
expect(getType(t)).toBe("Text");
|
||||
expect(getType(123)).toBe("Json");
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -241,3 +241,45 @@ it("handlers should still be usable after doc is dropped", () => {
|
|||
expect(map.toJson()).toStrictEqual({ k: 8 });
|
||||
});
|
||||
|
||||
|
||||
it("isContainer", () => {
|
||||
expect(isContainer("123")).toBeFalsy();
|
||||
expect(isContainer(123)).toBeFalsy();
|
||||
expect(isContainer(123n)).toBeFalsy();
|
||||
expect(isContainer(new Map())).toBeFalsy();
|
||||
expect(isContainer(new Set())).toBeFalsy();
|
||||
expect(isContainer({})).toBeFalsy();
|
||||
expect(isContainer(undefined)).toBeFalsy();
|
||||
expect(isContainer(null)).toBeFalsy();
|
||||
const doc = new Loro();
|
||||
const t = doc.getText("t");
|
||||
expect(isContainer(t)).toBeTruthy();
|
||||
expect(getType(t)).toBe("Text");
|
||||
expect(getType(123)).toBe("Json");
|
||||
})
|
||||
|
||||
it("getValueType", () => {
|
||||
// Type tests
|
||||
const doc = new Loro();
|
||||
const t = doc.getText("t");
|
||||
expectTypeOf(getType(t)).toEqualTypeOf<"Text">();
|
||||
expect(getType(t)).toBe("Text");
|
||||
expectTypeOf(getType(123)).toEqualTypeOf<"Json">();
|
||||
expect(getType(123)).toBe("Json");
|
||||
expectTypeOf(getType(undefined)).toEqualTypeOf<"Json">();
|
||||
expect(getType(undefined)).toBe("Json");
|
||||
expectTypeOf(getType(null)).toEqualTypeOf<"Json">();
|
||||
expect(getType(null)).toBe("Json");
|
||||
expectTypeOf(getType({})).toEqualTypeOf<"Json">();
|
||||
expect(getType({})).toBe("Json");
|
||||
|
||||
const map = doc.getMap("map");
|
||||
const list = doc.getList("list");
|
||||
const tree = doc.getTree("tree");
|
||||
expectTypeOf(getType(map)).toEqualTypeOf<"Map">();
|
||||
expect(getType(map)).toBe("Map");
|
||||
expectTypeOf(getType(list)).toEqualTypeOf<"List">();
|
||||
expect(getType(list)).toBe("List");
|
||||
expectTypeOf(getType(tree)).toEqualTypeOf<"Tree">();
|
||||
expect(getType(tree)).toBe("Tree");
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue