啊,所以你不是要重命名属性;只需从其中一个接口中删除任何冲突的属性。
这与object spread type operator 的想法非常相似,TypeScript 目前在类型级别没有将其作为语言的一部分。目前,类型系统将泛型扩展视为 intersection,这仅适用于非冲突属性。)在值/表达式级别,TypeScript 确实可以正确处理具体类型的扩展,因此您可以获得特定的 Zoo '通过说服类型系统你有一个Pet类型的值,一个Person类型的值,以及一个通过传播它们形成的值来寻找:
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
如果你不想乱搞值(特别是如果你没有任何东西)并且你想纯粹在类型级别上做这件事,你可以用 @ 自己制作一个类似传播的类型运算符987654323@ 和 conditional 类型。一位语言设计者建议使用 implementation 或 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<> 都不能保证使用 readonly 属性做“正确的事情”,特别是因为我不清楚正确的事情是什么。
好的,希望对您有所帮助。祝你好运!