Typescript:合并记录的联合成一个单一的记录?



是否可以执行以下类型转换?我一直在尝试使用映射类型,但我认为这实际上是不可能的……希望我是错的。

{
foo: 'bar',
type: 'A'
} |
{
foo: 'car',
type: 'B',
}

{
bar: 'A',
car: 'B'
}

您可以使用映射类型将每个foo值映射到相应的type值来实现这一点。类型Values<Pick<Base, 'foo'>>为您提供了所有键的并集,而Extract<Base, { foo: P }>['type']为给定的键P找到匹配的type

type Values<T> = T[keyof T]
type Base = {
foo: 'bar',
type: 'A'
}
|
{
foo: 'car',
type: 'B',
}
type Result = {
[P in Values<Pick<Base, 'foo'>>]: Extract<Base, { foo: P }>['type']
}

如果Base类型有两个以上的替代方案(update),那么还有一个替代解决方案也可以工作。:这是在另一个解决方案被编辑之前写的,现在它们都工作了),例如:

type Base =
{foo: 'bar', type: 'A'} | {foo: 'car',type: 'B'} | {foo: 'd',type: 'C'}

它需要一个实用程序类型TypeForFoo,它返回一个foo类型对象的foo类型,所以TypeForFoo<Base, 'car'>等于'B':

type TypeForFoo<B, F> = B extends {foo: F, type: infer T} ? T : never

这是有效的,因为条件类型分布在联合上,这意味着它应用于Base的每个备选项,之后将结果组合在一个联合中(因此never消失)。

对于TypeForFoo,最终对象类型可以写成
type Obj = {[F in Base['foo']]: TypeForFoo<Base, F>}
// inferred: Obj = {bar: 'A', car: 'B', d: 'C'}

打印稿操场