I'm using [email protected] and [email protected]
whenever I create a document from firestore i get an object of type firebase.firestore.DocumentReference
as expected
If I call the get(options?: firebase.firestore.GetOptions|undefined)
I'll get a object of type firebase.firestore.DocumentSnapshot
as expected
If i call data(options?: firebase.firestore.DataOptions|undefined)
I'll get either a firebase.firestore.DocumentData object or undefined, as expected
Now, on my manager object, I know what I'm writing to the databse, so I can make the assertion that whatever DocumentData you get out of my manager, you'll get a Client as shown
export interface Client {
name: string;
website?: string;
description?: string;
visible: boolean;
}
I want to create an interface for my manager object that expresses that. So I've tried:
export interface FirebaseDocumentSnapshot<T> extends $firebase.firestore.DocumentSnapshot {
data(options?: $firebase.firestore.SnapshotOptions | undefined): T|undefined
}
export interface FirebaseDocumentReference<T> extends $firebase.firestore.DocumentReference {
get(options?: $firebase.firestore.GetOptions | undefined): Promise<FirebaseDocumentSnapshot<T>>
}
The problem i've got is here:
const client: Client = mapClient(args);
const result: FirebaseDocumentReference<Client> = await $db.add(client);
the error is:
[ts]
Type 'DocumentReference' is not assignable to type 'FirebaseDocumentReference<Client>'.
Types of property 'get' are incompatible.
Type '(options?: GetOptions | undefined) => Promise<DocumentSnapshot>' is not assignable to type '(options?: GetOptions | undefined) => Promise<FirebaseDocumentSnapshot<Client>>'.
Type 'Promise<DocumentSnapshot>' is not assignable to type 'Promise<FirebaseDocumentSnapshot<Client>>'.
Type 'DocumentSnapshot' is not assignable to type 'FirebaseDocumentSnapshot<Client>'.
Types of property 'data' are incompatible.
Type '(options?: SnapshotOptions | undefined) => DocumentData | undefined' is not assignable to type '(options?: SnapshotOptions | undefined) => Client | undefined'.
Type 'DocumentData | undefined' is not assignable to type 'Client | undefined'.
Type 'DocumentData' is not assignable to type 'Client'.
Property 'name' is missing in type 'DocumentData'. [2322]
const result: FirebaseDocumentReference<Client>
How can i declare the interfaces so I can know the type of the resulting object?
The solution goes: Get the interested document (doc) and then: doc. ref. collection('Collection_Name'). add('Object_to_be_added') It is advisable to include a then/catch after the promise.
Is there any way to update a specific index from the array in Firestore? No, there is not! This is not possible because if you want to perform an update, you need to know the index of that particular element. When talking about Cloud Firestore arrays, the things are different that you might think.
A DocumentReference refers to a document location in a Cloud Firestore database and can be used to write, read, or listen to the location. There may or may not exist a document at the referenced location. A DocumentReference can also be used to create a CollectionReference to a subcollection.
Another alternative is to enter the document path directly in the Path field, e.g. myCollection/myDocumentId and click the Run button. Right-click on the left-most field (ID column) of the document and choose Rename Document.
A simple solution would be to cast the return data:
const client = snapshot.data() as Client
@gal-bracha's solution will "work" in the sense that the TypeScript compiler will assume client
is of type Client
, but it doesn't prevent a runtime error if bad data ended up in Firestore. A safer solution when dealing with any data external to your app is to use something like Yup to validate data explicitly:
import * as yup from "yup";
const clientSchema = yup.object({
name: yup.string(),
website: yup.string().url().notRequired(),
description: yup.string().notRequired(),
visible: yup.boolean()
});
// You can use this elsewhere in your app
export type Client = yup.InferType<typeof clientSchema>;
// Usage
const client = await clientSchema.validate(snapshot.data());
This is more defensive as clientSchema.validate
will throw an error if, for some reason, bad data ended up in Firestore. After validate()
, you're guaranteed, that client
is a Client
and not just telling the TypeScript compiler "treat this as a Client
even though at runtime, it may not be".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With