使用FirestoreDataConverter时子类无法赋值给父类DocumentReference问题
问题分析与解决
你遇到的问题核心是:子类Two中重新定义了私有属性reference,导致TypeScript认为这是一个和父类One的protected reference完全独立的属性,进而触发类型兼容性检查失败。
错误根源
- 父类
One的reference是DocumentReference<One>,子类Two的私有reference是DocumentReference<Two>,两者被视为不同属性,TypeScript会强制检查属性类型的兼容性。 FirestoreDataConverter<Two>无法赋值给FirestoreDataConverter<One>:因为转换器的toFirestore方法参数是逆变类型——父类转换器接受One类型的参数,而子类转换器仅接受更具体的Two类型,不符合逆变要求(需要参数类型更宽泛)。- 当
reference设为public时,TypeScript会将其视为对父类protected属性的重写(public可见性高于protected),此时会放宽部分类型检查,因此不会报错。
解决方案
方案1:用泛型父类统一类型(推荐)
让父类支持泛型,子类继承时指定自身类型,这样父类的reference会自动适配子类的DocumentReference类型,无需在子类中重新定义属性:
import { DocumentReference, FirestoreDataConverter, DocumentData } from "firebase/firestore"; abstract class One<T extends One<T>> { protected reference?: DocumentReference<T>; public abstract static converter: FirestoreDataConverter<T>; } class Two extends One<Two> { constructor(reference?: DocumentReference) { super(); this.reference = reference?.withConverter(Two.converter); } public static converter: FirestoreDataConverter<Two> = { toFirestore: (model: Two): DocumentData => { // 实现将Two对象转为Firestore文档的逻辑 return {}; }, fromFirestore: (snapshot) => { // 实现从Firestore快照转为Two对象的逻辑 return new Two(snapshot.ref); } }; }
方案2:避免属性名冲突
如果一定要在子类中使用私有属性,换一个和父类不重复的属性名,比如_reference,这样就不会触发父类属性的兼容性检查:
abstract class One { protected reference?: DocumentReference<One>; public static converter: FirestoreDataConverter<One>; } class Two extends One { private _reference?: DocumentReference<Two>; // 换个属性名 constructor(reference?: DocumentReference) { super(); this._reference = reference?.withConverter(Two.converter); } public static converter: FirestoreDataConverter<Two> = { // 实现转换器逻辑 toFirestore: () => ({}), fromFirestore: (snapshot) => new Two(snapshot.ref) }; }
内容的提问来源于stack exchange,提问作者Catogram
相关产品推荐
相关产品推荐

