Typescript interface conformance with firestore qu

2019-07-17 09:03发布

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?

3条回答
手持菜刀,她持情操
2楼-- · 2019-07-17 09:19

The solution you have is just typecasting the doc.data(). That is not a solution, its a workaround. Because, by doing so you might face run time errors.

So, what I would suggest is, just use :

const payment = doc.data()

In case of const, the typing will be automatically enforced.

OR

You can write a function which converts the DocumentData type to the Payment type. by adding the missing params.

查看更多
做自己的国王
3楼-- · 2019-07-17 09:20

Given that doc.data() always returns a DocumentData, which is just {[field: string]: any}, I don't think there's any better way to turn that into a Payment than casting. You could write:

const data = doc.data();
const payment = {amount: doc.amount, /*and so on for the remaining members*/};

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 just any (like the return of JSON.parse to give one example); you could file an issue on the project to propose that.

查看更多
The star\"
4楼-- · 2019-07-17 09:29

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

查看更多
登录 后发表回答