Skip to main content

Data Snapshot

This page discusses how DataSnapshot works.

info

DataSnapshot from get operation, onValue and onChild* linteners work in the same way.

note

There is no exportVal method and priority prop because priority are outdated approach.

Type Checks

import {
MetaTypeCreator,
ServerTimestamp,
NumericKeyRecord,
Removable,
createRef,
getDatabase,
get,
} from 'firesagejs'
export type Example = MetaTypeCreator<{
b:
| {
c: boolean | Removable
d: {
e: ServerTimestamp
}
}
| Removable
f: Record<string, 'a' | 'b' | 'c'>
i: NumericKeyRecord<boolean>
}>
const exampleRef = createRef<Example>(getDatabase())

;async () => {
const snapshot = await get(exampleRef('b')) // reading 'b'
const val = snapshot.val() // { c: boolean | null | undefined, d: { e: number } }
const exists = snapshot.exists() // boolean
const size = snapshot.size // number
const hasChild = snapshot.hasChild('d/e') // boolean, types of argument are all child of b, that is 'c', 'd' or 'd/e'.
const hasChildren = snapshot.hasChildren() // boolean
const json = snapshot.toJSON() // object, we have to type cast it
snapshot.forEach((child, index) => {
const data = child.val() // the data type of child is null or boolean or { e: number } because 'b' has 2 direct children: 'c' and 'd'
const ref = child.ref // DatabaseReference<Example, "b/c"> | DatabaseReference<Example, "b/d">

// use exhaustive check to narrow down types
if (child.key === 'c') {
// Typescript now know we are looking at node 'b/c'
const narrowedDataType = child.val() // boolean | null | undefined
const narrowedRef = child // DataSnapshot<Example, "b/c">
} else if (child.key === 'd') {
// Typescript now know we are looking at node 'b/d'
const narrowedDataType = child.val() // { e:number } | null
const narrowedRef = child // DataSnapshot<Example, "b/d">
}
})

const hasChild2 = snapshot.hasChild('abc') // not ok because 'abc' is not child of 'b'
}
get return types

tip

Child is also a snapshot and has access to properly typed forEach, val, key, size, exists, child, hasChild, hasChildren, toJSON.

So with child of child because data snapshots are recursively typed!

info

You see

  1. null because all read data are potentially null(no data).
  2. undefined because c union with Removable and Removable union the node with null and undefined.
  3. e is number because the read type of ServerTimestamp is number.
child data types

child ref types

get return types

narrowed data type

narrowed ref type

Understanding Error Messages

note

Due to complexity, this error message is too generic, will give it deeper thoughts in the future.

incorrect child relative path