typescript:扩展多种类型的模板化接口数组

Posted

技术标签:

【中文标题】typescript:扩展多种类型的模板化接口数组【英文标题】:typescript: Array of templated interface extending multiple types 【发布时间】:2021-12-21 09:25:34 【问题描述】:

这是我的问题的一个最小示例

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

它抛出这个错误

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'

我想要一个Speaker 数组,它接受任何类型的Living

感谢您的宝贵时间!

【问题讨论】:

【参考方案1】:

按照您定义事物的方式,Speaker&lt;Living&gt; 表示具有 speak 函数的对象,该函数接受 Person | Dog 作为其参数。当您创建michel 时,您有以下功能,如果给定Person,则可以正常工作:

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

但如果给定Person | Dog,它将无法工作,因为它试图访问狗的.arms 属性。这种不匹配和其他原因是打字稿告诉您不能将Speaker&lt;Person&gt; 分配给Speaker&lt;Living&gt; 的原因

如果您希望数组是对象的混合,其中一些使用Persons 作为其说话功能,其中一些使用Dogs,那么其类型将是:

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

编辑:如果您的 Living 联合很大,或者您希望扬声器在更多类型添加到 Living 时自动更新,那么您可以使用以下内容获取打字稿为您生成 Speaker&lt;Person&gt; | Speaker&lt;Dog&gt; 联合:

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

【讨论】:

好的,我明白了。有没有办法指定所有的生活而不是放置多个|?例如,如果我向 Living 添加一个新类型,我希望这个数组能够自动重新输入。 添加了如何做到这一点的示例 谢谢!它奏效了

以上是关于typescript:扩展多种类型的模板化接口数组的主要内容,如果未能解决你的问题,请参考以下文章

如何在 TypeScript 中表示包含多种类型的二维数组?

TypeScript 具有相同参数的多种返回类型

Typescript 扩展通用接口

TypeScript,接口(Interfaces),对象、数组和函数的类型

在 TypeScript 中作为类输入

涵盖数组和类型化数组的 TypeScript 接口