I’m making a basic Firebase call to retrieve a collection this way
import { getFirestore, collection, getDocs } from "firebase/firestore";
import { Invoice } from "../models/Invoice";
const db = getFirestore();
export const getInvoicesCollection = async () => {
try {
const snapshot = await getDocs(collection(db, "invoices"));
const docs: Invoice[] = snapshot.docs.map((doc) => ({
...doc.data(),
}));
console.log(docs);
} catch (error) {
console.error(error);
}
};
export default getInvoicesCollection;
The response object returned by Firebase is pretty fat so I map everything I need into a new one in this part:
const docs: Invoice[] = snapshot.docs.map((doc) => ({
...doc.data(),
}));
console.log(docs);
And I get the result in the browser:
But TypeScript complains that:
Type '{ [x: string]: any; }[]' is not assignable to type 'Invoice[]'.
Type '{ [x: string]: any; }' is missing the following properties from type 'Invoice': id, createdAt, paymentDue, description, and 8 more.
If I get it right, it says that my variable is an array of objects with a single property which is a string and can be anything? How can I make it aware of what the object really looks like?
>Solution :
The type that doc.data() returns is { [x: string]: any; }, meaning an object with any number or properties with a string for a key, each of which can have any value. There’s no way for typescript to figure out a more specific type than this, since the database could return pretty much anything.
So since typescript can’t figure out the type, you will need to assert what the type is:
const docs: Invoice[] = snapshot.docs.map((doc) => ({
...doc.data() as Invoice,
}));
Note: by using a type assertion, you are telling typescript not to check your work, and just trust you. If you make a mistake and the database actually contains different types of objects, typescript won’t be able to tell you about that.
