How do I work with Firebase and my own Typescript interfaces?
ie. I have a function here that I'm going to need the full Payment
object, (not just the delta), so I get that via the DocumentReference
object.
function doSomethingWithPayment(payment: Payment) {
console.log(payment.amount);
}
exports.resolveStripeCharge = functions.firestore.document('/payments/{paymentId}')
.onWrite((change : Change <DocumentSnapshot>) => {
change.after.ref.get().then((doc: DocumentSnapshot )=> {
const payment : Payment = doc.data(); // tslint warning here.
doSomethingWithPayment(payment);
})
[ts]
Type 'DocumentData' is not assignable to type 'Payment'.
Property 'amount' is missing in type 'DocumentData'.
const payment: Payment
I get that the returned object wont necessarily conform the interface - but in anycase -what should I do here - if I want to enforce typing?
Do I just use:
const payment : Payment = <Payment>doc.data();
Or is there a much nicer solution?
So, what I would suggest is, just use :
const payment = doc.data()
In case of
const
, the typing will be automatically enforced.OR
Given that
doc.data()
always returns aDocumentData
, which is just{[field: string]: any}
, I don't think there's any better way to turn that into aPayment
than casting. You could write:without a cast, but I don't think that's better in practical terms. It would make more sense to me for
DocumentData
to be justany
(like the return ofJSON.parse
to give one example); you could file an issue on the project to propose that.Not sure if this helps, but the way I think of it is that the type you have in your program and the types you send and recieve from Firestore are different types.
So, typescript has this 'Partial' feature that takes an interface and makes all of the fields optional. That way even if the object isn't complete, it will still conform and provide you with intellisense.
So, I do this :
export type dataUpdate<T> = Partial<T>;
Then, I do :
const userPayload: dataUpdate<User> = snapshot/typecase as User