I'm trying to convert data from Firestore into a type in Angular. Though I'm struggling on how to use a converter.
This is my model:
import { QueryDocumentSnapshot } from "@angular/fire/firestore";
export interface Song {
title: string;
lyrics: string;
}
export const songConverter = {
toFirestore: (data: Song) => data,
fromFirestore: (snapshot: QueryDocumentSnapshot) => snapshot.data() as Song
}
And this is my service:
import { Injectable, inject } from '@angular/core';
import { Firestore, collection, doc, getDoc, getDocs } from '@angular/fire/firestore';
import { Song, songConverter } from './song.model';
@Injectable({
providedIn: 'root'
})
export class SongService {
firestore: Firestore = inject(Firestore);
getSongs(): Promise<Song[]> {
return getDocs(collection(this.firestore, 'songs').withConverter(songConverter));
}
getSong(id: string): Promise<Song> {
return getDoc(doc(this.firestore, 'songs', id).withConverter(songConverter));
}
}
The errors I receive are:
Type 'Promise<DocumentSnapshot<Song, Song>>' is not assignable to type 'Promise'. Type 'DocumentSnapshot<Song, Song>' is missing the following properties from type 'Song': title, lyrics
and:
Type 'Promise<QuerySnapshot<Song, Song>>' is not assignable to type 'Promise<Song[]>'. Type 'QuerySnapshot<Song, Song>' is missing the following properties from type 'Song[]': length, pop, push, concat, and 28 more.
Where am I going wrong?
The code you want looks something like this. I'd use map
to extract the Song
object from each DocumentSnapshot
in the QuerySnapshot
.
function getSongs(): Promise<Song[]> {
return getDocs(collection(this.firestore, 'songs').withConverter(songConverter))
.then((querySnap: QuerySnapshot<Song, Song>) => {
return querySnap.docs.map((docSnap: DocumentSnapshot<Song, Song>) => docSnap.data());
})
}
Edit: or use async/await for improved readability.
async function getSongs(): Promise<Song[]> {
const querySnap: QuerySnapshot<Song, Song> =
await getDocs(collection(this.firestore, 'songs').withConverter(songConverter));
return querySnap.docs.map((docSnap: DocumentSnapshot<Song,Song>) => docSnap.data());
}