简体   繁体   English

打字稿:扩展多种类型的模板化接口数组

[英]typescript: Array of templated interface extending multiple types

Here is a minimal example of my problem这是我的问题的最小示例

interface Dog {
  legs: number;
}

interface Person {
  arms: number;
}

type Living = Person | Dog;

interface Speaker<T extends Living> {
  speak: (living: T) => void;
};

const michel: Speaker<Person> = { speak: (person) => console.log(`I have ${person.arms} arms`) };

const speakers: Array<Speaker<Living>> = [michel];

It throw this error它抛出这个错误

Type 'Speaker<Person>' is not assignable to type 'Speaker<Living>'.
  Type 'Living' is not assignable to type 'Person'.
    Property 'harms' is missing in type 'Dog' but required in type 'Person'

I would like to have an array of Speaker that accepts any type of Living .我想要一个可以接受任何类型LivingSpeaker数组。

Thanks for your time!谢谢你的时间!

With the way you've defined things, Speaker<Living> means an object with a speak function that takes in a Person | Dog根据您定义事物的方式, Speaker<Living>表示一个具有说话功能的对象,该对象接收Person | Dog Person | Dog as its argument. Person | Dog作为它的论点。 When you create michel , you have the following function, which works fine if given a Person :当你创建michel ,你有以下功能,如果给定一个Person ,它可以正常工作:

(person) => console.log(`I have ${person.arms} arms`)

But it would not work if given a Person | Dog但是如果给定一个Person | Dog就行不通了Person | Dog , because it's trying to access the .arms property of a dog. Person | Dog ,因为它试图访问狗的.arms属性。 That mismatch and others is why typescript is telling you that Speaker<Person> cannot be assigned to Speaker<Living>这种不匹配和其他不匹配就是为什么打字稿告诉你Speaker<Person>不能分配给Speaker<Living>

If you want the array to be a mix of objects, some of which take Person s for their speak function, some of which take Dog s, then the type for that will be:如果您希望数组是对象的混合,其中一些将Person作为其发言功能,其中一些采用Dog ,那么其类型将是:

const speakers: Array<Speaker<Person> | Speaker<Dog>> = [michel];

EDIT: if your Living union is large, or you want speakers to update automatically when more types are added into Living , then you can use the following to get typescript to generate the Speaker<Person> | Speaker<Dog>编辑:如果您的Living union 很大,或者您希望在将更多类型添加到Living时自动更新扬声器,那么您可以使用以下内容获取打字稿以生成Speaker<Person> | Speaker<Dog> Speaker<Person> | Speaker<Dog> union for you: Speaker<Person> | Speaker<Dog>工会给你:

type Distribute<T> = T extends Living ? Speaker<T> : never;

const speakers: Array<Distribute<Living>> = [michel];
// speakers is of type Array<Speaker<Person> | Speaker<Dog>>

Playground link 游乐场链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM