将对象类型的动态列表组合为一种大型对象类型

时间:2020-08-28 06:05:43

标签: typescript typescript-typings

我有一个动态生成的类型,该类型生成一个数组,其中每个元素可以是一组类型中的任何一种,例如:

type Elements = (TypeA | TypeB | TypeC | ...)[] // this is dynamically generated

我有一种方法可以将数组中的每种类型提取为常规的“或”类型而没有问题

type IndividualElements = ArrayTypes<Elements>
// the above is results in dynamically generating this type:
type IndividualElements = TypeA | TypeB | TypeC | ...

这有效,但是现在我想设置一个对象,该对象包含数组中所有类型的每个键/值。基本上是创建一个包含所有属性的大对象,除了动态之外,类似这样:

type CombinedElement = TypeA & TypeB & TypeC & ...

我可以手动将其写出来,但是由于每种类型都是根据JSON模式自动生成的,所以我宁愿拥有一种类型机制来动态地进行操作。这可能吗?

1 个答案:

答案 0 :(得分:1)

这实际上很有趣,花了我一段时间:根据另一个答案,您可以对条件类型和派生类型进行一些疯狂的操作,基本上可以使用这种类型将Union转换为Intersection:

type UnionToIntersection<U> =
    (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;

所以让我们测试一下整个事情:

type test = UnionToIntersection<{} | { test: string } | { foo: number }>;
//produces to { test: string } & { foo: number }

编辑: 您甚至可以通过从数组“即时”生成联合类型来使整件事更进一步:

type UnionToIntersection<U> =
    (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;

type list = {} | { test: string } | { foo: number };
type test = UnionToIntersection<list[number]>; //list[number] produces the union type
//also produces { test: string } & { foo: number }