Document databases like Firebase work great with JavaScript but they can get really messy really fast if you’re not very strict with your data models. TypeScript is the perfect companion here and luckily the Firebase database functions can be easily typed in a way that will help you to keep your data consistent.
Replace this:
// profileCollection is typed as any
const profileCollection = collection(db, 'userprofiles')
With this:
export const createCollection = <T = DocumentData>(collectionName: string) => {
return collection(db, collectionName) as CollectionReference<T>
}
// profileCollection is typed as CollectionReference<UserProfile>
const profileCollection = createCollection<UserProfile>('userprofiles')
..and now your collection operations, including documents and snapsots, are fully typed.
The great Vueuse helper collection also has one very useful function to use with Firebase snapshots:
// From: https://github.com/vueuse/vueuse/blob/main/packages/firebase/useFirestore/index.ts
export function getData<T>(docRef: DocumentSnapshot<T> | QueryDocumentSnapshot<T>) {
const data = docRef.data()
if (data) {
Object.defineProperty(data, 'id', {
value: docRef.id.toString(),
writable: false,
})
}
return data
}
With getData
you can cast document snapshots in the wanted type while making sure the IDs are easy to work with. For example:
// profile is typed as UserProfile | undefined
const profile = getData<UserProfile>(await getDoc(doc(profileCollection, uid)))