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
null
because all read data are potentiallynull
(no data).undefined
becausec
union withRemovable
andRemovable
union the node withnull
andundefined
.e
isnumber
because the read type ofServerTimestamp
isnumber
.
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