【问题标题】:typescript: Array of templated interface extending multiple typestypescript:扩展多种类型的模板化接口数组
【发布时间】: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

感谢您的宝贵时间!

【问题讨论】:

    标签: javascript arrays typescript typescript-generics


    【解决方案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 添加一个新类型,我希望这个数组能够自动重新输入。
    • 添加了如何做到这一点的示例
    • 谢谢!它奏效了
    猜你喜欢
    • 2021-08-07
    • 2019-04-07
    • 2015-04-01
    • 2020-09-29
    • 2020-05-04
    • 2022-12-06
    • 2018-04-09
    • 2018-06-20
    • 1970-01-01
    相关资源
    最近更新 更多