如何为Firebase 9.x Firestore查询指定自定义TypeScript类型?
在Firebase 9.x + TypeScript中指定Firestore查询的自定义类型
问题场景
我用TypeScript和Firebase 9.x SDK查询Firestore,代码如下:
const q = query(myCollectionRef); const snapshot = await getDocs(q); snapshot.forEach((doc) => { // doc.data() is never undefined for query doc snapshots console.log(doc.id, " => ", doc.data()); });
当前返回的是通用的QuerySnapshot<DocumentData>,我想把它指定为自定义数据接口QuerySnapshot<MyType>,试了下面的写法:
const q = query<MyType>(myCollectionRef); const snapshot = await getDocs<MyType>(q);
但TypeScript直接报错:
TS2345: Argument of type 'CollectionReference<DocumentData>' is not assignable to parameter of type 'Query<MyType>'. Types of property 'converter' are incompatible. Type 'FirestoreDataConverter<DocumentData> | null' is not assignable to type 'FirestoreDataConverter<MyType> | null'. Type 'FirestoreDataConverter<DocumentData>' is not assignable to type 'FirestoreDataConverter<MyType>'. The types returned by 'fromFirestore(...)' are incompatible between these types. Type 'DocumentData' is not assignable to type 'MyType'.
解决方法
方法1:直接给集合引用指定泛型
报错根源是myCollectionRef默认是CollectionReference<DocumentData>类型,和Query<MyType>不匹配。先给集合引用绑定自定义类型,再创建查询:
// 先定义你的自定义接口 interface MyType { name: string; age: number; // 其他业务字段 } // 获取集合时直接指定泛型 const myCollectionRef = collection(db, "你的集合名") as CollectionReference<MyType>; // 后续查询无需额外加泛型,自动继承类型 const q = query(myCollectionRef); const snapshot = await getDocs(q); // 此时snapshot就是QuerySnapshot<MyType> snapshot.forEach((doc) => { const data = doc.data(); // data类型为MyType console.log(doc.id, " => ", data); });
方法2:用数据转换器(更严谨,推荐)
如果需要处理Firestore特殊类型(比如Timestamp转Date、GeoPoint处理),用数据转换器既能做类型转换,又能绑定类型:
interface MyType { name: string; age: number; createdAt: Date; // 希望把Firestore的Timestamp转成Date } // 创建转换器,处理前后端类型映射 const myTypeConverter: FirestoreDataConverter<MyType> = { toFirestore(data: MyType): DocumentData { return { ...data, createdAt: Timestamp.fromDate(data.createdAt), // 转成Firestore支持的Timestamp }; }, fromFirestore(snapshot: QueryDocumentSnapshot): MyType { const data = snapshot.data(); return { ...data, createdAt: data.createdAt.toDate(), // 把Timestamp转回Date } as MyType; }, }; // 给集合绑定转换器,自动关联MyType const myCollectionRef = collection(db, "你的集合名").withConverter(myTypeConverter); // 查询自动继承类型 const q = query(myCollectionRef); const snapshot = await getDocs(q); // snapshot是QuerySnapshot<MyType>,doc.data()直接是MyType类型 snapshot.forEach((doc) => { const data = doc.data(); console.log(doc.id, " => ", data.createdAt); // createdAt是Date类型 });
内容的提问来源于stack exchange,提问作者Kong
相关产品推荐
相关产品推荐

