问题
我想定义一个带有宠物的人,这个宠物是一些扩展自Animal
的东西,而不仅仅是一个Animal
:
interface Person {
name: string
pet: extends Animal //I'm looking for something that would work here
}
我尝试过的
假设我们有以下这些接口:
interface Animal {
name: string
}
interface Fish extends Animal {
swim: () => void
}
interface Bird extends Animal {
fly: () => void
}
1. 使用父类型
我知道可以这样做:
interface Person {
name: string
pet: Animal // Not what I want, because it needs to be only things that extend Animal
}
但这将会妨碍推理。因为如果pet
不是Fish
,那么它应该是Bird
。但是这样它同样可以是一个普通的Animal
。
2. 联合类型
为了只使用扩展Animal
的类型,我可以使用联合类型自己选择它们:
interface Person {
name: string
pet: Fish | Bird // Not what I want, because I would need to update it with new animals
}
但是如果我想创建更多的动物类型,每次都必须更新Person
。
例如,如果我添加:
interface Mole extends Animal {
dig: () => void
}
我希望能够自动将Mole
作为宠物添加到Person
中,而不需要显式地将其添加,只需将pet: Fish | Bird
更改为pet: Fish | Bird | Mole
。
摘要
我正在寻找一种方法,可以接受任何扩展Animal
的东西,但不包括父级Animal
本身,而无需每次出现新动物时都更新它。在TypeScript中如何实现?
注意
我不需要Animal
作为一个接口存在,但如果它可以保持接口形式,那就太好了。
Person
作为类型的所有地方提供一个类型参数。但我想我可以在那里(滥用)使用Person<Animal>
... 另外,我正在权衡之前和未来的Person
键入所需的额外工作,还是只是使用pet: Fish | Bird | Mole
。在我的代码库中,只要添加更多的Animal
时只需要更新Person
,这似乎更实用一些。 - CodingNeeLPerson<Animal>
,那么可以为泛型添加默认值(interface Person<T extends Animal = Animal>
),然后简单地使用Person
就行了。这样就不需要到处更新了。 - Olian04pet.fly()
,但如果我默认为Animal
,那么即使我们知道它不是Fish
,我也需要先确定它实际上是Bird
。 - CodingNeeLT
)变量。例如,请查看我一段时间前编写的这个随机ts-playrgound。 - Olian04