打字稿:扩展接口时更改冲突的属性名称

时间:2019-05-09 16:22:07

标签: typescript inheritance

是否可以使用打字稿进行类似的操作,重命名属性名称或其他名称?

interface Person {
    name: string
    age: number
}

interface Pet {
    age: string
}

interface Zoo extends Pet, Person {}

没有收到此错误:

  

接口“ Zoo”不能同时扩展类型“ Person”和“ Pet”   类型“人”和“宠物”的命名属性“年龄”不同。ts(2320)

[编辑]

我正在寻找一种获得此结果的方法:

interface Zoo {
    name: string
    age: number
}

1 个答案:

答案 0 :(得分:1)

啊,所以您不是要重命名属性。只需从接口之一中删除任何冲突的属性。

这与object spread type operator的概念非常相似,TypeScript在类型级别上目前还不属于该语言的一部分。当前,类型系统将通用扩展名视为intersection,这仅适用于不冲突的属性。)在值/表达式级别,TypeScript会正确处理具体类型的扩展名,因此您可以获得特定的{{ 1}}通过说服类型系统来寻找您具有Zoo类型的值,Pet类型的值以及通过散布它们而形成的值:

Person

如果您不想随意使用值(特别是如果您无处闲逛),并且只想在类型级别上执行此操作,则可以使用{ {3}}和mapped类型。一位语言设计师建议使用interface Person { name: string age: number } interface Pet { age: string trained: boolean // I added this because otherwise Zoo=Person which is weird } declare const person: Person; // pretend we have a person declare const pet: Pet; // pretend we have a pet const zoo = { ...pet, ...person }; // spread them into a new variable type ZooType = typeof zoo; // get the type of that variable // type ZooType = { // name: string; // age: number; // trained: boolean; // } interface Zoo extends ZooType { }; // make it an interface because why not 中的conditional,在围绕可选/只读/等属性的一些注意事项方面可以很好地发挥作用。

对于您来说,由于没有可选属性或只读属性,因此这是一个更简单的实现,我将其称为Spread<L,R>

Merge<L, R>

您会看到它的行为类似于上述价值水平价差:

type Merge<L, R> = R & Pick<L, Exclude<keyof L, keyof R>>;

注意事项:如果interface Zoo extends Merge<Pet, Person> { }; declare const zoo: Zoo; zoo.name; // string zoo.age; // number zoo.trained; // boolean age中为可选,则Person将使Merge<Pet, Person>age中为可选。 可能是您想要的,但是价差不会以这种方式表现; Zoo始终需要一个{...pet, ...person},因为age需要一个。这样一来,Pet类似于Zoo["age"],上面链接的string | number运算符将更正确地处理。同样,Spread<L, R>和链接的Merge<>都不能保证通过Spread<>属性来做“正确的事情”,特别是因为我不清楚那是正确的事情。

好的,希望能有所帮助。祝你好运!