I think you already found a solution. Types are just a view on the shared data. You need to define beforehand how you want to interpret the top-level types (e.g. define “name” as Y.Text: getType(“name”, Y.Text)).
Is there any consistent/proper method to get the YTypes for all the shared types in my doc?
Not really. You are supposed to know beforehand which types exists.
Does this approach still work? While I can see the “share” property when logging a Y.Doc on a browser console, accessing that property always yields an empty Map (i.e., one with length 0 - however, if I log that Map as well, the browser still sees its entries - although the length is 0!)
That’s really strange…
[Edit] What I found out so far:
the loop shown above should probably be changed to
doc.share.forEach((value, key) => {
let type = value.constructor.name
})
the strange output shown in my browser’s console was produced because doc.share was inspected before doc was completely synced from an IndexeddbPersistence. By waiting for the synced event, the output could be consolidated
Strange, when the entries of doc.share are loaded from persistence, they all seem to be created using the same constructor - independent of their original type.
But how does one then determine that original type?
[Edit] here is how I determine the type of a shared y.Doc entry (limited to y.Map, y.Array and y.Text)
function TypeOfEntry (Entry) {
if ((Entry._map instanceof Map) && (Entry._map.size > 0)) {
return 'y.Map'
}
if ((Entry._start != null) && ('arr' in Entry._start.content)) {
return 'y.Array'
}
if ((Entry._start != null) && ('str' in Entry._start.content)) {
return 'y.Text'
}
return undefined
}
const sharedDoc = new Y.Doc()
const Persistence = new IndexeddbPersistence('Yjs-Test-Content',sharedDoc)
Persistence.on('synced', () => {
sharedDoc.share.forEach((Value,Key) => {
console.log(Key, TypeOfEntry(Value), Value)
})
})
ok, here is my current approach to detect the type of a shared type (or an element or entry of a shared type) regardless whether it is a top-level Y.Doc entry, a Y.Map entry or a Y.Array element
function TypeOf (Entry) {
switch (typeof Entry) {
case 'undefined':
case 'boolean':
case 'number':
case 'string': return typeof Entry
case 'object':
switch (true) {
case (Entry == null): return 'null'
case Array.isArray(Entry): return 'tuple'
case (Entry instanceof Uint8Array): return 'Uint8Array'
case (Entry instanceof Y.Doc): return 'Y.Doc'
case (Entry instanceof Y.Map): return 'Y.Map'
case (Entry instanceof Y.Array): return 'Y.Array'
case (Entry instanceof Y.Text): return 'Y.Text'
case (Entry instanceof Y.XmlElement): return 'Y.XmlElement'
case (Entry instanceof Y.XmlFragment): return 'Y.XmlFragment'
case (Entry instanceof Y.XmlText): return 'Y.XmlText'
case (Entry._map instanceof Map) && (Entry._map.size > 0): return 'Y.Map'
case (Entry._start != null) && ('arr' in Entry._start.content): return 'Y.Array'
case (Entry._start != null) && ('str' in Entry._start.content): return 'Y.Text'
case (Entry._start != null) && ('type' in Entry._start.content): return 'Y.XmlFragment'
default: return 'struct'
}
default: return typeof Entry
}
}
tuples are plain JS arrays and structs plain JS objects
Right now, I cannot detect Y.XmlText and Y.XmlElement - they are reported as Y.Text or Y.XmlFragment, resp.
Here is the current version of my Yjs data type detection method:
/**** tries to determine the type of a given Yjs data item ****/
// note: "Y.XmlElement"s will be identified as "Y.Map" and "XmlText"s as "Y.Text"
function TypeOf (Entry) {
switch (typeof Entry) {
case 'undefined':
case 'boolean':
case 'number':
case 'string': return typeof Entry
case 'object':
switch (true) {
case (Entry == null): return 'null'
case Array.isArray(Entry): return 'tuple'
case (Entry instanceof Uint8Array): return 'Uint8Array'
case (Entry instanceof Y.Doc): return 'Y.Doc'
case (Entry instanceof Y.Map): return 'Y.Map'
case (Entry instanceof Y.Array): return 'Y.Array'
case (Entry instanceof Y.Text): return 'Y.Text'
case (Entry instanceof Y.XmlElement): return 'Y.XmlElement'
case (Entry instanceof Y.XmlFragment): return 'Y.XmlFragment'
case (Entry instanceof Y.XmlText): return 'Y.XmlText'
case (Entry._map instanceof Map) && (Entry._map.size > 0): return 'Y.Map'
case (Entry._start != null) && ('arr' in Entry._start.content): return 'Y.Array'
case (Entry._start != null) && ('str' in Entry._start.content):
case (Entry._start != null) && ('len' in Entry._start.content): return 'Y.Text'
case (Entry._start != null) && ('type' in Entry._start.content): return 'Y.XmlFragment'
default: return 'struct'
}
default: return typeof Entry
}
}