Typescript 获取通用接口扩展

Typescript 获取通用接口扩展,typescript,types,set-theory,Typescript,Types,Set Theory,考虑以下接口: interface A { name: string; value: number; sub: { query: number[] }, old: number; } interface B { name: string; value: string; sub: { query: string[] }, new: boolean; } 我正在寻找一个通用解决方案来获得接口/类型: inte

考虑以下接口:

interface A {
   name: string;
   value: number;
   sub: {
       query: number[]
   },
   old: number;
}

interface B {
   name: string;
   value: string;
   sub: {
       query: string[]
   },
   new: boolean;
}
我正在寻找一个通用解决方案来获得接口/类型:

interface C extends B, A {
}
其中C类似于接口D:

interface D {
   name: string;
   value: string;
   sub: {
       query: string[]
   },
   old: number;
   new: boolean;
}
所以我可以有一个功能:

function merge<T, U>(t: T, u: U): interface C extends T, U {
  // Merge objects
  // ...
  return obj;
}
函数合并(t:t,u:u):接口C扩展t,u{
//合并对象
// ...
返回obj;
}
它不必是一个接口。我认为,一种类型也可以做到这一点


类型
A&B
不起作用,因为这样我就有了一个交集(例如
value
将是类型
number&string
)。

我使用这个
MergeReplace
类型来更准确地键入
对象。赋值({},T,S)

请注意,
MergeReplace
是右偏的,因此如果
T
S
共享一个属性,但类型不同,则选择
S
中的类型


查看以获取更多信息。

我使用此
MergeReplace
类型可以更准确地键入
Object.assign({},T,S)

请注意,
MergeReplace
是右偏的,因此如果
T
S
共享一个属性,但类型不同,则选择
S
中的类型

查看更多信息。

我想我知道了:

type MergeRightBiased<TLeft, TRight> =
  TLeft extends any[] ? TRight :
    TRight extends any[] ? TRight :
      TLeft extends object ?
        TRight extends object ? {
          // All properties of Left and Right, recursive
          [P in keyof TLeft & keyof TRight]: MergeRightBiased<TLeft[P], TRight[P]>
        } & {
          // All properties of Left not in Right
          [P in Exclude<keyof TLeft, keyof TRight>]: TLeft[P];
        } & {
          // All properties of Right not in Left
          [P in Exclude<keyof TRight, keyof TLeft>]: TRight[P]
        }
          // Prefer Right
          : TRight
        : TRight;
类型合并=
TLeft是否扩展了任何[]?TRight:
TRight扩展任何[]?TRight:
TLeft扩展对象?
TRight扩展对象?{
//左和右的所有属性,递归
[P in keyof TLeft和keyof TRight]:合并右偏
} & {
//左的所有属性不在右
[P in Exclude]:TLeft[P];
} & {
//右的所有属性不在左
[P in Exclude]:TRight[P]
}
//优先权
:TRight
:TRight;
谢谢@Oblosys的帮助

我想我明白了:

type MergeRightBiased<TLeft, TRight> =
  TLeft extends any[] ? TRight :
    TRight extends any[] ? TRight :
      TLeft extends object ?
        TRight extends object ? {
          // All properties of Left and Right, recursive
          [P in keyof TLeft & keyof TRight]: MergeRightBiased<TLeft[P], TRight[P]>
        } & {
          // All properties of Left not in Right
          [P in Exclude<keyof TLeft, keyof TRight>]: TLeft[P];
        } & {
          // All properties of Right not in Left
          [P in Exclude<keyof TRight, keyof TLeft>]: TRight[P]
        }
          // Prefer Right
          : TRight
        : TRight;
类型合并=
TLeft是否扩展了任何[]?TRight:
TRight扩展任何[]?TRight:
TLeft扩展对象?
TRight扩展对象?{
//左和右的所有属性,递归
[P in keyof TLeft和keyof TRight]:合并右偏
} & {
//左的所有属性不在右
[P in Exclude]:TLeft[P];
} & {
//右的所有属性不在左
[P in Exclude]:TRight[P]
}
//优先权
:TRight
:TRight;

谢谢@Oblosys的帮助

除了交集类型外,还有另一种高级类型-联合类型,它可以接受数字或字符串值。这里有更多文档-union不会做你想做的吗?不。A | B不一样。除了交集类型,还有另一种高级类型-union类型,可以接受数字或字符串值。这里有更多文档-union不会做你想做的吗?不,A | B不一样。谢谢。这是正确的方向。但它不支持嵌套对象。不,它不支持,它只支持最右边的对象。我认为在不为不同类型的属性(如
)创建交集类型的情况下,支持合并嵌套对象类型会很困难,但也许有一个聪明的解决方案。谢谢。这是正确的方向。但它不支持嵌套对象。不,它不支持,它只支持最右边的对象。我认为在不为不同类型的属性(如
)创建交集类型的情况下支持合并嵌套对象类型将是一件棘手的事情,但也许有一个聪明的解决方案。啊,是的,这是一个有趣的解决方案!如果某个对象仅位于右侧(例如,
Merge
),则有点狡猾,但是
T
上的附加条件可以解决这一问题。我希望更对称的
[P in Exclude]:U[P]
而不是
U
,但我想这是因为正确的偏见。(顺便说一下,@username pings只在评论中起作用)啊,是的,这是一个有趣的解决方案!如果某个对象仅位于右侧(例如,
Merge
),则有点狡猾,但是
T
上的附加条件可以解决这一问题。我希望更对称的
[P in Exclude]:U[P]
而不是
U
,但我想这是因为正确的偏见。(顺便说一句,@username pings只在注释中起作用)
type MergeRightBiased<TLeft, TRight> =
  TLeft extends any[] ? TRight :
    TRight extends any[] ? TRight :
      TLeft extends object ?
        TRight extends object ? {
          // All properties of Left and Right, recursive
          [P in keyof TLeft & keyof TRight]: MergeRightBiased<TLeft[P], TRight[P]>
        } & {
          // All properties of Left not in Right
          [P in Exclude<keyof TLeft, keyof TRight>]: TLeft[P];
        } & {
          // All properties of Right not in Left
          [P in Exclude<keyof TRight, keyof TLeft>]: TRight[P]
        }
          // Prefer Right
          : TRight
        : TRight;