Skip to content

Instantly share code, notes, and snippets.

@eoguvo
Last active June 5, 2024 14:38
Show Gist options
  • Save eoguvo/4103373740868cdc133cafcfefb66d5d to your computer and use it in GitHub Desktop.
Save eoguvo/4103373740868cdc133cafcfefb66d5d to your computer and use it in GitHub Desktop.
transform the crazy firebase output in a generic type, the way it should be since the init
import { DocumentData, DocumentSnapshot, QuerySnapshot } from "firebase-admin/firestore";
type withDocId<T> = T & { docId: string }
type SingleDocument = DocumentSnapshot<DocumentData>;
type QueryDocuments = QuerySnapshot<DocumentData>;
type Snapshot = SingleDocument | QueryDocuments;
type SnapshotNullable = Snapshot | null;
const checkSingle = (snapshot: Snapshot): snapshot is SingleDocument => {
return "id" in snapshot || !Array.isArray(snapshot.docs);
};
const toObject = <T extends object>(data: DocumentSnapshot<DocumentData>): withDocId<T> => {
return { ...data.data() as T, docId: data.id };
};
type getReturn<T, U> = U extends SingleDocument ? T : T[];
export const parseFirebaseSnapshot = <R extends object, S extends SnapshotNullable = SingleDocument>(
snapshot: S
): getReturn<withDocId<R>, S> => {
if (!snapshot) {
return {} as getReturn<withDocId<R>, S>;
}
const isSingle = checkSingle(snapshot);
if (isSingle) {
return toObject(snapshot);
}
return snapshot.docs.map(toObject<R>) as getReturn<withDocId<R>, S>;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment