Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to type Firebase JS SDK errors in try-catch blocks?

Given that function that saves documents to Firestore, I'm trying to type the err object.

async function saveToFirestore(obj: SOME_OBJECT, collection: string, docId: string) {
  try {
    await firebase.firestore().collection(collection).doc(docId).set(obj);
  }
  catch(err: firebase.firestore.FirestoreError) {
    // THIS DOESN'T SEEM TO BE POSSIBLE
  }
}

Also tried with firebase.FirebaseError

I'm getting this error:

enter image description here

What I'm looking for is a way to get auto completion on the error object that comes from Firebase. How do people usually handle this? Should the error object always be typed as any or unknown? Why?


UPDATE

Given the fact that it's not possible to type the catch(err) directly, my goal was to have something like this:

catch(err) {
  if (err instanceof firebase.FirebaseError) {  // <--- THIS DOES NOT WORK
    throw `something for the FirebaseError`
  }
  else {
    throw `something else for other error types`
  }
}

But from the discussion on the issue that Frank pointed out on his answer, it seems that this is not possible.

_We don't allow type annotations on catch clauses because there's really no way to know what type an exception will have. You can throw objects of any type and system generated exceptions (such as out of memory exception) can technically happen at any time. Even if we had a Java-like notion of throws annotations it is not clear that we could ever really rely on them. (And, it is also not clear that they work all that well in Java, but that's another discussion.)_

We don't narrow any in type guards unless we know the exact type you're narrowing to. For example, if you check typeof x === "string" we will indeed narrow an any to string because we know for sure that is the exact type of x. That isn't the case with instanceof. Specifically, you might check x instanceof Base, but x might actually be an instance of a class derived from Base. If we narrowed x to type Base you'd see errors on access to properties of the derived class even though there is nothing wrong with the code. Now, before you argue those errors would be fine, keep in mind that the declared type of x is any, so you've already said you want no checking. We take that as an indication that we should issue errors only when we're 100% sure they're errors. And we only know that if we know the exact type.

like image 313
cbdeveloper Avatar asked Sep 01 '25 20:09

cbdeveloper


2 Answers

As far as I know you can't specify a type on a catch clause, because that would suggest that you're only catching a certain type of error, which isn't possible in the language.

The common workaround to get a typed variable is to declare a local variable immediately inside the catch block:

catch(e) {
  const err: firebase.firestore.FirestoreError = e;
}

Also see this discussion on the topic: https://github.com/microsoft/TypeScript/issues/8677#issuecomment-220385124

like image 71
Frank van Puffelen Avatar answered Sep 03 '25 17:09

Frank van Puffelen


I tried this, and I solved my problem

I use instanceof

try {
  await signInWithCredential(auth, authProvider)
} catch (e) {
  const err = e instanceof FirebaseError
  if(err){
    console.log(e.code)
  }
}

}

like image 24
Eduardo Hernández Soto Avatar answered Sep 03 '25 15:09

Eduardo Hernández Soto