【问题标题】:Constrain method signatures through interface using generics in TypeScript在 TypeScript 中使用泛型通过接口约束方法签名
【发布时间】:2018-11-28 09:40:29
【问题描述】:

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

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

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

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&lt;Dog&gt; 方法只接受和/或返回Dogs,但它可以是任何Animal

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

【问题讨论】:

  • 在提供的示例中,DogCat 在结构上是等效的。只需添加一些鉴别器属性(例如type: 'dog'),你就会得到一个错误
  • Dog 和 Cat 不同,但只有可选参数,例如:claw?: Claw

标签: typescript oop interface extends implements


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    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; }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多