TypeScript:如何扩展基类并收窄animal属性的type为Dog?
实现DogOwner类的两种方法
首先得补全Dog、Cat、Fish的类型定义(原代码未给出,这里提供基础示例):
type Dog = { breed: string }; type Cat = { hasClaws: boolean }; type Fish = { waterType: 'fresh' | 'salt' };
推荐方案:泛型基类
把AnimalOwner改成泛型抽象类,让子类指定具体的动物类型,能安全收窄animal的类型:
abstract class AnimalOwner<T extends Animal> { public name: string; public animal: T; constructor(name: string, animal: T) { this.name = name; this.animal = animal; } } type Animal = { type: Dog | Cat | Fish, foo: string, bar: string, }; // 定义DogOwner,指定泛型为type仅含Dog的Animal类型 class DogOwner extends AnimalOwner<Omit<Animal, 'type'> & { type: Dog }> { // 可在此添加DogOwner专属的方法或属性 } // 使用示例 const goldenRetriever = { type: { breed: 'Golden Retriever' }, foo: 'woof', bar: 'good boy' }; const alice = new DogOwner('Alice', goldenRetriever); // 此时alice.animal.type的类型自动收窄为Dog
备选方案:重写属性收窄类型
如果无法修改原基类,直接在DogOwner里重写animal属性,明确指定其type为Dog:
abstract class AnimalOwner { public name: string; public animal: Animal; constructor(name: string, animal: Animal) { this.name = name; this.animal = animal; } } type Animal = { type: Dog | Cat | Fish, foo: string, bar: string, }; class DogOwner extends AnimalOwner { // 重写animal属性,收窄type为Dog public animal: Omit<Animal, 'type'> & { type: Dog }; constructor(name: string, animal: typeof DogOwner.prototype.animal) { super(name, animal); this.animal = animal; } }
补充说明
- 泛型方案更灵活,后续新增
CatOwner、FishOwner时可直接复用基类,类型检查更严谨。 - 重写属性的方案适合无法改动原基类的场景,但要保证子类的
animal类型是基类Animal的子类型,避免类型冲突。
内容的提问来源于stack exchange,提问作者Mushr00m
相关产品推荐
相关产品推荐

