Skip to content

Commit 2450248

Browse files
authored
fix: update EphemeralStore to support generic types (#718)
* fix: update EphemeralStore to support generic types * fix: add delete for ephemeral
1 parent 2dd4eff commit 2450248

2 files changed

Lines changed: 38 additions & 9 deletions

File tree

crates/loro-wasm/index.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,8 @@ export class Awareness<T extends Value = Value> {
249249
* store2.apply(encoded);
250250
* ```
251251
*/
252-
export class EphemeralStore<T extends Value = Value> {
253-
inner: EphemeralStoreWasm<T>;
252+
export class EphemeralStore<T extends Record<string, Value> = Record<string, Value>> {
253+
inner: EphemeralStoreWasm;
254254
private timer: number | undefined;
255255
private timeout: number;
256256
constructor(timeout: number = 30000) {
@@ -263,21 +263,25 @@ export class EphemeralStore<T extends Value = Value> {
263263
this.startTimerIfNotEmpty();
264264
}
265265

266-
set(key: string, value: T) {
267-
this.inner.set(key, value);
266+
set<K extends keyof T>(key: K, value: T[K]) {
267+
this.inner.set(key as string, value);
268268
this.startTimerIfNotEmpty();
269269
}
270270

271-
get(key: string): T | undefined {
272-
return this.inner.get(key);
271+
delete<K extends keyof T>(key: K) {
272+
this.inner.delete(key as string);
273273
}
274274

275-
getAllStates(): Record<string, T> {
275+
get<K extends keyof T>(key: K): T[K] | undefined {
276+
return this.inner.get(key as string);
277+
}
278+
279+
getAllStates(): Partial<T> {
276280
return this.inner.getAllStates();
277281
}
278282

279-
encode(key: string): Uint8Array {
280-
return this.inner.encode(key);
283+
encode<K extends keyof T>(key: K): Uint8Array {
284+
return this.inner.encode(key as string);
281285
}
282286

283287
encodeAll(): Uint8Array {

crates/loro-wasm/tests/ephemeral.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,31 @@ describe("EphemeralStore", () => {
116116
});
117117
});
118118

119+
it("generic type", () => {
120+
// Define a type to test type inference
121+
const store = new EphemeralStore<{ foo: string, bar: number }>(10);
122+
// This should compile correctly
123+
store.set("foo", "bar");
124+
store.set("bar", 1);
125+
126+
// Verify runtime values are correct
127+
expect(store.get("foo")).toBe("bar");
128+
expect(store.get("bar")).toBe(1);
129+
130+
// Type inference for get should work too
131+
const foo: string | undefined = store.get("foo");
132+
const bar: number | undefined = store.get("bar");
133+
expect(foo).toBe("bar");
134+
expect(bar).toBe(1);
135+
136+
// @ts-expect-error - This should fail type checking as "foo" expects string
137+
store.set("foo", 123);
138+
// @ts-expect-error - This should fail type checking as "bar" expects number
139+
store.set("bar", "string");
140+
// @ts-expect-error - This should fail type checking as "baz" is not in the type
141+
store.set("baz", "value");
142+
});
143+
119144
it("subscribe", () => {
120145
const store = new EphemeralStore(10);
121146
let callTimes = 0;

0 commit comments

Comments
 (0)