Reputation: 239
The following statement throws a type error. Why?
const x: Chat = { ...doc.data(), id: doc.id }
The error is:
Type '{ id: string; }' is missing the following properties from type 'Chat': message, name, createdAt ts(2739)
The spread operand provides three elements of the object, and the id is provided by the second operand.
I am using Vue 3.0.0, firebase 9.0.2 and typescript 4.1.5
here is the whole component:
import { ref } from 'vue'
import { projectFirestore, Timestamp } from '@/firebase/config'
// import Chat from '@/types/Chat'
interface Chat {
id?: string
message: string
name: string | null
createdAt: Timestamp
}
import {
collection as collect,
query,
orderBy,
onSnapshot,
} from 'firebase/firestore'
const getCollection = (collection: string) => {
const documents = ref<Chat[]>()
const error = ref<string>()
try {
const q = query(
collect(projectFirestore, collection),
orderBy('createdAt', 'desc')
)
const unsubscripe = onSnapshot(q, (querySnapshot) => {
const results: Chat[] = []
querySnapshot.forEach((doc) => {
const x: Chat = { ...doc.data(), id: doc.id }
doc.data().createdAT && results.push(x)
})
documents.value = results
})
} catch (err) {
if (err instanceof Error) {
error.value = err.message
} else {
throw Error('Unknown Error')
}
}
return { documents, error }
}
export default getCollection
I am new to typescript, but this does seem strange. Thanks in advance
Upvotes: 2
Views: 2288
Reputation: 50920
As @TJCrowder commented, you can check what the data()
method returns. It returns object of type DocumentData
and Typescript doesn't really know what the contents are. You can try using a type assertion like this and specify that the object will be of type Chat
:
const x = { ...doc.data(), id: doc.id } as Chat
However, this can lead to mistyping documents that don't exist (when doc.exists === false
- usually found when working with a DocumentReference
rather than queries). Instead of asserting the type on the line with doc.data()
, you can assert the type of the CollectionReference
that you used in the query instead. This works the same for a DocumentReference
too. Typescript will make sure that you've properly handled the case where a document doesn't exist first.
collect(projectFirestore, collection) as CollectionReference<Chat>
// ...
// x will be a Chat object when `doc.exists === true` (which it is in queries)
const x = { ...doc.data(), id: doc.id }
You can read more about Type Assertion
in Typescript's documentation.
Upvotes: 3