I'm trying to map angularfire2's promises into typed observables. This is my class:
export class RestService<T extends Entity> {
constructor(
protected afAuth: AngularFireAuth,
protected store: AngularFirestore,
protected readonly collectionName: string) {
this.collection = store.collection<T>(collectionName);
}
protected collection: AngularFirestoreCollection<any>;
all(): Observable<Array<T>> {
return from(this.collection
.snapshotChanges()
.pipe(
map(action => mapActionArray(action)),
catchError((error: any) => {
throw new ApiError(error);
})
)
);
}
}
/**
* Override Firestore errors with common app errors.
* @param error - Firestore error
*/
function mapError(error: any): Observable<ApiError> {
return throwError(new ApiError(error));
}
function mapDocument<T extends Entity>(doc: DocumentSnapshot<any>): T {
return {
id: doc.id,
...doc.data()
};
}
Notice the all() method, I want to map any error in the catchError, but the thing is I get this type error:
TS2322: Type 'Observable<{}[]>' is not assignable to type 'Observable'. Type '{}[]' is not assignable to type 'T[]'. Type '{}' is not assignable to type 'T'.
I fixed it by changing the return type to Observable<{} | Array>, but that would require using the same types whenever I use this service, I don't find it good. How do I work around this? I want to be able to type my services and in beforehand map the errors into a proper CustomError object (this includes mapping codes to messages).
Btw, I also tried using the throwError from RXJS.
Thanks in advance.
Answering my own question, I had to use the catchError before the map operator. So:
all(): Observable<Array<T>> {
return from(this.collection
.snapshotChanges()
.pipe(
map(action => mapActionArray(action)),
catchError((error: any) => {
throw new ApiError(error);
})
)
);
}
Would become
all(): Observable<Array<T>> {
return from(this.collection
.snapshotChanges()
.pipe(
catchError((error: any) => {
throw new ApiError(error);
}),
map(action => mapActionArray(action))
)
);
}
Hope it helps