-
-
Notifications
You must be signed in to change notification settings - Fork 643
Open
Labels
A-Developer-ExperienceA-Technical-DebtT-TaskTasks for the team like planningTasks for the team like planning
Description
In this PR it became apperant that we do not have a good nested map solution.
This comment (by @robintown) proposes a good solution:
#5028 (comment)
In fact, this pattern of shuffling around nested maps is so common in the JS SDK that I feel like it deserves to be turned into a set of reusable functions. It takes a bit of type magic, but I played around with it a bit and I think something like this would make for a pretty convenient API:
type NestedMap<K extends unknown[], V> = K extends [infer K1, ...infer K_] ? Map<K1, NestedMap<K_, V>> : V function getNested<K extends [unknown, ...unknown[]], M extends NestedMap<K, unknown>>(map: M, ...keys: K): M extends NestedMap<K, infer V> ? V | undefined : never { let result: any = map for (const key of keys) result = result?.get(key) return result } function setNested<K extends [unknown, ...unknown[]], V, M extends NestedMap<K, V>>(map: M, value: V, ...keys: K): void { let m: any = map for (let i = 0; i < keys.length - 1; i++) { let inner = m.get(keys[i]) if (inner === undefined) { inner = new Map() m.set(keys[i], inner) } m = inner } m.set(keys[keys.length - 1], value) } function deleteNested<K extends [unknown, ...unknown[]], M extends NestedMap<K, unknown>>(map: M, ...keys: K): boolean { if (keys.length === 1) { return map.delete(keys[0]) } else { const inner = map.get(keys[0]) as Map<unknown, unknown> | undefined if (inner === undefined) return false const [key, ...keys_] = keys // @ts-ignore const result = deleteNested(inner, ...keys_) if (inner.size === 0) map.delete(key) return result } }Usage looks like this:
const myMap = new Map<number, Map<string, number>>() setNested(myMap, 999, 1, 'foo') const y = getNested(myMap, 1, 'foo') // y = 999 deleteNested(myMap, 1, 'foo') // now myMap is emptyThen with nested maps of 3+ layers being less painful, this could even help us avoid the
${stickyKey}${sender}
hack found in this file.
This change was not added as part of #5028.
This issue tracks adding such a feature and using it in all places of the js-sdk where it is helpful.
robintown
Metadata
Metadata
Assignees
Labels
A-Developer-ExperienceA-Technical-DebtT-TaskTasks for the team like planningTasks for the team like planning