在TypeScript中有没有一种方法可以将“extends T”用作类型?

igetnqfo  于 2023-02-10  发布在  TypeScript
关注(0)|答案(2)|浏览(128)

问题

我想定义一个养宠物的人,它是扩展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
}

我希望Person自动接受Mole作为宠物,而不通过将pet: Fish | Bird更改为pet: Fish | Bird | Mole来显式添加它。

总结

我正在寻找一种方法,它可以接受任何扩展Animal的内容,但不能接受父Animal本身,而不必在每次出现新动物时更新它。

备注

我不需要Animal作为一个接口存在,但是如果它能保持一个接口就好了。

k97glaaz

k97glaaz1#

这就是泛型的用武之地:

interface Person<T extends Animal> {
  name: string
  pet: T
}

let personWithBirdPet: Person<Bird>;
let personWithFishPet: Person<Fish>;
let personWithMolePet: Person<Mole>;

泛型有点像“类型参数”,就像你可以为函数(function(foo, bar) {})定义“值参数”一样,我们可以为大多数类型结构(包括函数function<A, B>(foo: A, bar: B) {},和你上面看到的接口)定义称为泛型的“类型参数”。
当使用泛型时,我们可以通过使用extends关键字来对泛型应用约束。例如,function<A extends number>(value: A) {}将与编写function(value: number) {}非常相似。使用泛型的版本更强大,但也更冗长。在这个简单的function示例中,使用泛型将是多余的。然而,在您的interface情况下,使用泛型将是您所需要的。

记住鸭子打字

由于typescript是鸭子类型的(如果它走路像鸭子,说话像鸭子,那么它就是鸭子),所以您可能会得到一些您需要注意的意外行为。
例如,你可以让一个人养一只普通的动物作为宠物:

let personWithGenericPet: Person<Animal>;

或者你可以让一个人养一只宠物,它不“延伸”动物,但看起来像动物:

let personWithStrangePet: Person<{ name: 'bob' }>;

..说到这个,Person看起来像动物,所以你可以有一个人和一个人作为宠物:

let personWithPersonPet: Person<Person<Animal>>;

这些问题不是由泛型引起的,而是 typescript 如何工作的核心问题。
运动场

llycmphe

llycmphe2#

像这样的东西有用吗?

interface Person<T extends Animal> {
    name: string;
    pet: T;
}

相关问题