使用TypeScript中的泛型通过接口约束方法签名

时间:2018-06-19 12:12:48

标签: typescript oop interface extends implements

例如,我有两个接口扩展了第三个接口

interface Animal { /* name, etc */ };
interface Dog extends Animal { /* dog specific things */ }
interface Cat extends Animal { /* cat specific things */ }

我想为两个扩展类“ Model”创建类, 简化了数据库的工作

interface AnimalModel<A extends Animal> {
  all(): Promise<A[]>;
  get(id: string): Promise<A>;
  create(user: A): Promise<void>;
}

我继续

class DogModel implements AnimalModel<Dog> {
  // Expected TypeScript to complain, but it does not, because Cat does extend the animal?
  async create(cat: Cat) { /* actual implementation, query the db */ }
}

我在做什么错?我希望class DogModel implements AnimalModel<Dog>方法只能接受和/或返回Dog,但是它可以是任何Animal

ps:我正在考虑使用抽象类,所以我可能会以不同的方式解决它,这个问题仍然没有答案,我想了解我的代码(问题中的那个)出了什么问题

2 个答案:

答案 0 :(得分:1)

Typescript使用结构兼容性来确定类型兼容性,因此具有相同结构的两个类型是兼容的。如果您的两个接口具有兼容的结构,则不会收到错误。使用您发布的代码(具有空接口),这两个接口显然兼容,但是此示例也会触发错误:

interface Dog extends Animal { eat(): void;  }
interface Cat extends Animal { eat(): void; scratch(): void; }

如果类型包含不兼容的字段,则将出现错误,例如添加区分字段,或具有dog中必需的字段,而cat中不存在的字段/方法。这种类型将触发错误:

interface Dog extends Animal { eat(): void; bark(): void }
interface Cat extends Animal { eat(): void; scratch(): void; }

答案 1 :(得分:1)

TypeScript没有抱怨,因为DogCat接口仅包含可选属性。当它们具有不同的必需属性时,TypeScript会正确引发错误